要向窗口添加控件,可以使用AddControl方法。 或者,您可以使用API函数CreateWindowEx,但是您将不得不自己做缩放。
除了控件的注册类名,在许多情况下,您可以使用更容易记住的别名。 例如。 您可以使用“STATUSBAR”而不是“MSCTLS_STATUSBAR32”。
AddControl方法还为所有Windows控件提供默认样式。 因此,您可以保存打字,除非您需要使用不同的样式。
例如,添加一个可以使用的按钮
pWindow.AddControl("Button", pWindow.hWindow, IDCANCEL, "&Close", 350, 250, 75, 23)
代替
pWindow.AddControl("Button", pWindow.hWindow, IDCANCEL, "&Close", 350, 250, 75, 23, WS_CHILD OR WS_VISIBLE OR WS_TABSTOP OR BS_PUSHBUTTON OR BS_CENTER OR BS_VCENTER
有关预定义类名和样式的列表,请参阅AddControl Method方法。
如果应用程序是DPI感知,则使用AddControl方法创建的控件将根据DPI设置进行缩放。
AddControl还提供了两种方法来轻松地对控件进行子类化。
对于第一种方式,在Windows XP之前使用,您需要传递子类化过程的地址,例如
pWindow.AddControl("Button", pWindow.hWindow, IDC_BUTTON, "Click me", 350, 250, 75, 23, , , , CAST(WNDPROC, @Button_SubclassProc))
并使用像这样的回调:
' ========================================================================================
' 处理子类Button窗口的消息。
' ========================================================================================
FUNCTION Button_SubclassProc ( _
BYVAL hwnd AS HWND, _ ' // Control window handle
BYVAL uMsg AS UINT, _ ' // Type of message
BYVAL wParam AS WPARAM, _ ' // First message parameter
BYVAL lParam AS LPARAM _ ' // Second message parameter
) AS LRESULT
SELECT CASE uMsg
CASE WM_GETDLGCODE
' // 所有键盘输入
FUNCTION = DLGC_WANTALLKEYS
EXIT FUNCTION
CASE WM_LBUTTONDOWN
MessageBoxW(GetParent(hwnd), "Click", "FreeBasic", MB_OK)
EXIT FUNCTION
CASE WM_KEYDOWN
SELECT CASE LOWORD(wParam)
CASE VK_ESCAPE
SendMessageW(GetParent(hwnd), WM_CLOSE, 0, 0)
EXIT FUNCTION
END SELECT
CASE WM_DESTROY
' // 必需:删除控件子类
SetWindowLongPtrW hwnd, GWLP_WNDPROC, CAST(LONG_PTR, RemovePropW(hwnd, "OLDWNDPROC"))
END SELECT
FUNCTION = CallWindowProcW(GetPropW(hwnd, "OLDWNDPROC"), hwnd, uMsg, wParam, lParam)
END FUNCTION
' ========================================================================================
第二种方式使用了API函数SetWindowSubclass。 除了传递回调过程的地址之外,它还允许将控件的标识符和指向CWindow类的指针传递。
pWindow.AddControl("Button", pWindow.hWindow, IDC_BUTTON, "Click me", 350, 250, 75, 23, , , , _
CAST(WNDPROC, @Button_SubclassProc), IDC_BUTTON, CAST(DWORD_PTR, @pWindow))
这种方法的主要优点是我们可以对所有的子类控件使用相同的回调,并且可以很容易的识别哪一个触发消息,如果需要使用它,也可以指向他的父CWindow类。 SetWindowSubclass也消除了在此线程中解释的旧的子类方法的缺点: 子类化控件
使用此方法子类化的控件的回调函数示例:
' ========================================================================================
' 处理子类Button窗口的消息。
' ========================================================================================
FUNCTION Button_SubclassProc ( _
BYVAL hwnd AS HWND, _ ' // Control window handle
BYVAL uMsg AS UINT, _ ' // Type of message
BYVAL wParam AS WPARAM, _ ' // First message parameter
BYVAL lParam AS LPARAM, _ ' // Second message parameter
BYVAL uIdSubclass AS UINT_PTR, _ ' // The subclass ID
BYVAL dwRefData AS DWORD_PTR _ ' // Pointer to reference data
) AS LRESULT
SELECT CASE uMsg
CASE WM_GETDLGCODE
' // All keyboard input
FUNCTION = DLGC_WANTALLKEYS
EXIT FUNCTION
CASE WM_LBUTTONDOWN
MessageBoxW(GetParent(hwnd), "Click", "FreeBasic", MB_OK)
EXIT FUNCTION
CASE WM_KEYDOWN
SELECT CASE LOWORD(wParam)
CASE VK_ESCAPE
SendMessageW(GetParent(hwnd), WM_CLOSE, 0, 0)
EXIT FUNCTION
END SELECT
CASE WM_DESTROY
' // REQUIRED: Remove control subclassing
RemoveWindowSubclass hwnd, @Button_SubclassProc, uIdSubclass
END SELECT
FUNCTION = DefSubclassProc(hwnd, uMsg, wParam, lParam)
END FUNCTION
' ========================================================================================
这两种方法都是可选的。 因此,您可以使用自己的方式来对控件进行子类化。
警告:您不能使用子类助手函数来跨线程来跨越一个窗口。