导航:  CWindow Class > Tutorial >

Adding controls

上一页返回章节概述下一页

要向窗口添加控件,可以使用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

' ========================================================================================

 

这两种方法都是可选的。 因此,您可以使用自己的方式来对控件进行子类化。

 

警告:您不能使用子类助手函数来跨线程来跨越一个窗口。