我有一種抽象問題,關於使用直接Win32進行GUI編程。由於我以前的GUI經歷是使用Swing在Java中進行的,因此我習慣於讓佈局管理器在調整窗口大小時自動調整/重新定位按鈕和內容。是否有類似的內置到Win32 API中,或者是否需要在每次重繪時使用絕對位置手動重新計算大小和位置?我認爲這實際上是做這件事的方式,因爲我沒有偶然發現任何看起來像MSDN文檔中的佈局管理的東西,但正如那些(在我看來)有點迷糊的我可能錯過了它。在Win32 GUI程序中的佈局
感謝您的幫助!
我有一種抽象問題,關於使用直接Win32進行GUI編程。由於我以前的GUI經歷是使用Swing在Java中進行的,因此我習慣於讓佈局管理器在調整窗口大小時自動調整/重新定位按鈕和內容。是否有類似的內置到Win32 API中,或者是否需要在每次重繪時使用絕對位置手動重新計算大小和位置?我認爲這實際上是做這件事的方式,因爲我沒有偶然發現任何看起來像MSDN文檔中的佈局管理的東西,但正如那些(在我看來)有點迷糊的我可能錯過了它。在Win32 GUI程序中的佈局
感謝您的幫助!
編號Win32 API不包含調整控件大小和重新定位的代碼。你必須自己寫或使用一個庫。微軟在Visual Studio中提供了一個資源編輯器,還提供了MFC(一個圍繞API的C++包裝器),但是這兩者都不能解決實際問題(自動調整大小和重新定位)。我已經使用了wxWidgets,它比MFC(在我看來)更加連貫,並且有一個名爲「sizers」的概念,它可以解決調整大小和重新定位的問題。
感謝您澄清! – 2012-04-04 03:14:17
你需要看看ATL(與Visual C++一起發貨),並相應地,WTL(未發貨,需要下載)。
他們幾乎完全編譯爲「直接Win32」,同時提供了一個很好的C++包裝。它們非常輕巧(幾乎可以實現沒有的重量,實際上它是99%的調用的直接Win32),但WTL設計用來模仿MFC的功能,所以它仍然非常有特色。儘管如此,你仍然需要使用C++來獲得半精準的效果。
最簡單的方法是使用CDialogResize<CYourDialog>
在類似
// Put ATL includes before here..
#include <atlcrack.h> // Include this from WTL for message map
#include <atlframe.h> // Include this from WTL for CDialogResize
class CYourDialog : CDialogImpl<CYourDialog>, CDialogResize<CYourDialog>
{
BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
{
this->DlgResize_Init(); // Initialize the positions
}
BEGIN_MSG_MAP_EX(CYourDialog) // Learn about message maps if you haven't
MSG_WM_INITDIALOG(OnInitDialog)
CHAIN_MSG_MAP(CDialogResize<CYourDialog>) // Chain to the parent
END_MSG_MAP()
BEGIN_DLGRESIZE_MAP(CYourDialog)
DLGRESIZE_CONTROL(IDOK, DLSZ_MOVE_Y) // Layout for "OK" button
END_DLGRESIZE_MAP()
};
DLGRESIZE_CONTROL()
是佈局的心臟 - DLSZ_MOVE_Y
,例如,說要垂直移動IDOK
。你也可以將它們分組,但它會變得棘手(有時候我不明白髮生了什麼)......但是一旦你做對了,其實並沒有那麼糟糕。 :)
這裏是一個自包含的例子:
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#include <atlbase.h>
extern CComModule _Module;
#include <atlapp.h>
#include <atlcrack.h>
#include <atlwin.h>
#include <atlframe.h>
#include "resource.h"
class CMyDialog : public CDialogImpl<CMyDialog>, CDialogResize<CMyDialog>
{
public:
enum { IDD = IDD_DIALOG1 };
private:
BOOL OnInitDialog(CWindow wndFocus, LPARAM)
{
this->DlgResize_Init();
return TRUE;
}
void OnOK(UINT, int, HWND) { this->EndDialog(ERROR_SUCCESS); }
void OnCancel(UINT, int, HWND) { this->EndDialog(ERROR_CANCELLED); }
BEGIN_MSG_MAP_EX(CMyDialog)
MSG_WM_INITDIALOG(OnInitDialog)
COMMAND_HANDLER_EX(IDOK, BN_CLICKED, OnOK)
COMMAND_HANDLER_EX(IDCANCEL, BN_CLICKED, OnCancel)
CHAIN_MSG_MAP(CDialogResize<CMyDialog>)
END_MSG_MAP()
BEGIN_DLGRESIZE_MAP(CMyDialog)
DLGRESIZE_CONTROL(IDOK, DLSZ_MOVE_X | DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDCANCEL, DLSZ_MOVE_X | DLSZ_MOVE_Y)
END_DLGRESIZE_MAP()
};
CComModule _Module;
int WINAPI _tWinMain(
HINSTANCE hInstance, HINSTANCE hInstPrevious,
LPTSTR lpCmdLine, int nCmdShow)
{
_Module.Init(NULL, hInstance);
{
CMyDialog dialog;
dialog.DoModal();
}
_Module.Term();
}
要編譯它,你還需要一個名爲resource.h
與在同一個項目文件夾中的文件,內容如下:
#define IDD_DIALOG1 101
#define IDR_RT_MANIFEST1 103
並將一個名爲Sample.rc
的文件添加到項目中,該項目可以使用Visual Studio進行編輯,幷包含對話框佈局:
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
#include "afxres.h"
#undef APSTUDIO_READONLY_SYMBOLS
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif
#ifdef APSTUDIO_INVOKED
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif
IDD_DIALOG1 DIALOGEX 0, 0, 316, 180
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,205,159,50,14
PUSHBUTTON "Cancel",IDCANCEL,259,159,50,14
END
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_DIALOG1, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 309
TOPMARGIN, 7
BOTTOMMARGIN, 173
END
END
#endif
#endif
#ifndef APSTUDIO_INVOKED
#endif
@NathanMcCrina:ATL實際上只是一個Win32的C++接口/包裝器 - 如果你使用的是C++,如果你使用C風格的API,那麼你會給自己一個很難的時刻 - 它會增加* nothing *和讓你遵循不好的做法(例如很多全局變量,這是一個壞主意,但是很容易犯錯)。至於DirectX:我很確定它們會很好地融合在一起 - 畢竟它與Win32沒有什麼不同,因爲它是一回事。 ATL的完整示例是否有幫助(可能沒有DirectX,只是如何顯示對話框)?我可以做一個對話並告訴你如何,這真的不那麼難。 – Mehrdad 2012-04-04 03:27:05
當然,我不會對例子說不! – 2012-04-04 03:33:54
@NathanMcCrina:查看更新。 – Mehrdad 2012-04-04 04:01:29
我有一些可能適用於純Win32 API調用的MFC代碼:http://stackoverflow.com/a/5739620/5987 – 2012-04-04 03:43:06