2014-05-25 1 views
2

그래서 미리 정의 된 클래스 (예 : 단추 클래스에 대한 사용자 지정 WndProc 만들기)에 대한 내 자신의 사용자 지정 메시지 proc을 정의 할 수 있도록 Win32에서 미리 정의 된 창 클래스를 서브 클래 싱하는 연습을하고 있습니다. 대부분은 그렇지만 WM_COMMAND 메시지를 새 메시지 proc에 자동으로 보내지는 못합니다. WM_COMMAND에 대한 부모 창에서 사례를 설정하고 wParam을 확인한 다음 WM_COMMAND 메시지를 보낸 하위 창에 대해 각각의 새 메시지 proc를 호출하지만 다른 모든 명령과 마찬가지로 자동으로 수행하는 것이 좋습니다. 지금까지 내가 정의한 사용자 정의 메시지 proc에서 시도한 다른 모든 WM_에 대해 부모님의 메시지 프로 시저에서 자동으로 전달 된 것을 알 수 있지만 WM_COMMAND 메시지는 명시 적으로 리디렉션하지 않는 한 표시되지 않습니다. 나는 WM_COMMAND 메시지를 부모 윈도우에 보낼 것이다. 서브 클래 싱 방식은 내가 설정 한 방법과 같지만 누군가가 왜 그런지 설명 할 수 있거나, 내가 속한 모든 메시지를 지시하기 위해해야 ​​할 일이 무엇인지를 설명 할 수있다. 단추 창을 내가 정의한 커스텀 WndProc에 추가하면 매우 만족 스러울 것이다.Win32 서브 클래 싱 - 메시지 정보

코드 : 디자인으로

#include <Windows.h> 
#include <windowsx.h> 

#define IDC_BUTTON 0 


LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 
LRESULT CALLBACK WndProcButton (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 

HWND g_hwndButton   = NULL; 
WNDPROC g_wndProcButtonOrigianl = NULL; 
BOOL g_bSeeingMouse   = FALSE; 

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 
        LPSTR szCmdLine, int iCmdShow) 
{ 
    static TCHAR szClassName[] = TEXT ("HelloWin") ; 
    HWND   hwnd ; 
    MSG   msg ; 
    WNDCLASS  wndclass ; 

    wndclass.style   = CS_HREDRAW | CS_VREDRAW ; 
    wndclass.lpfnWndProc = WndProc ; 
    wndclass.cbClsExtra = 0 ; 
    wndclass.cbWndExtra = 0 ; 
    wndclass.hInstance  = hInstance ; 
    wndclass.hIcon   = LoadIcon (NULL, IDI_APPLICATION) ; 
    wndclass.hCursor  = LoadCursor (NULL, IDC_ARROW) ; 
    wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; 
    wndclass.lpszMenuName = NULL ; 
    wndclass.lpszClassName = szClassName ; 

    if (!RegisterClass (&wndclass)) 
    { 
      MessageBox (NULL, TEXT ("This program requires Windows NT!"), 
         szClassName, MB_ICONERROR) ; 
      return 0 ; 
    } 

    hwnd = CreateWindow (szClassName,    // window class name 
          TEXT ("The Hello Program"), // window caption 
          WS_OVERLAPPEDWINDOW,  // window style 
          CW_USEDEFAULT,    // initial x position 
          CW_USEDEFAULT,    // initial y position 
          CW_USEDEFAULT,    // initial x size 
          CW_USEDEFAULT,    // initial y size 
          NULL,      // parent window handle 
          NULL,      // window menu handle 
          hInstance,     // program instance handle 
          NULL) ;      // creation parameters 

    ShowWindow (hwnd, iCmdShow) ; 
    UpdateWindow (hwnd) ; 

    while (GetMessage (&msg, NULL, 0, 0)) 
    { 
      TranslateMessage (&msg) ; 
      DispatchMessage (&msg) ; 
    } 
    return msg.wParam ; 
} 


LRESULT CALLBACK WndProcButton (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    switch(message) 
    { 
    case WM_COMMAND: 
     MessageBox(hwnd, TEXT("Test box"), TEXT("Test box"), MB_OK); 
     SetFocus(g_hwndButton); 
     break; 
    default: 
     if(!g_bSeeingMouse && GetCapture() == hwnd) 
     { 
      g_bSeeingMouse = TRUE; 
      SetWindowText(hwnd, L"Ok +mouse"); 
     } 
     else if(g_bSeeingMouse && GetCapture() != hwnd) 
     { 
      g_bSeeingMouse = FALSE; 
      SetWindowText(hwnd, L"Ok"); 
     } 
     break; 
    } 
    return CallWindowProc(g_wndProcButtonOrigianl, hwnd, message, wParam, lParam); 
} 

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    HDC   hdc ; 
    PAINTSTRUCT ps ; 
    RECT  rect ; 

    switch (message) 
    { 
    case WM_CREATE: 
     g_hwndButton = CreateWindow(L"Button",           // predefined class 
             L"Ok",            // button text 
             (WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON),   // styles 
             // Size and poition values are given explicitly, because 
             // the CW_USEDEFAULT constant gives zero values for buttons. 
             10,             // starting x position 
             10,             // starting y position 
             100,             // button width 
             30,             // button height 
             hwnd,             // parent window 
             (HMENU)IDC_BUTTON,         // no menu 
             (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), 
             NULL);            // pointer not needed 
     SetFocus(g_hwndButton); 
     g_wndProcButtonOrigianl = (WNDPROC)SetWindowLongPtr(g_hwndButton, GWLP_WNDPROC, (LONG_PTR)WndProcButton); 
      return 0 ; 

    case WM_PAINT: 
      hdc = BeginPaint (hwnd, &ps) ; 

      GetClientRect (hwnd, &rect) ; 

      DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect, 
        DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; 

      EndPaint (hwnd, &ps) ; 
      return 0 ; 

    case WM_DESTROY: 
      PostQuitMessage (0) ; 
      return 0 ; 
    } 
    return DefWindowProc (hwnd, message, wParam, lParam) ; 
} 

답변

2

WM_COMMANDWM_NOTIFY 메시지는 컨트롤의 부모 창으로 전송됩니다. API가 API를 생성 한 컨트롤로 API를 자동으로 보내도록하는 방법은 없습니다. 부모 창은 필요에 따라 처리해야합니다. 그것을 피할 수는 없습니다.

원래 Borland에서 작성했으며 현재 Embarcadero 소유 인 VCL 프레임 워크에서 간단한 시스템을 사용하여 이러한 메시지를 전달합니다. 부모 창에서 이러한 메시지 중 하나를 받으면 메시지를 사용자 정의 범위에 놓은 오프셋으로 메시지 ID를 증가시킨 다음 해당 메시지에 지정된 자식 HWND로 메시지를 전달합니다. 따라서 WM_COMMANDCN_COMMAND이되고 WM_NOTIFYCN_NOTIFY이되며, 이는 하위 컨트롤의 창 프로 시저에서 찾을 수 있습니다. 예를 들어

:

#define MY_COMMAND (WM_COMMAND + some_offset) 
#define MY_NOTIFY (WM_NOTIFY + some_offset) 

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    switch (message) 
    { 
    case WM_COMMAND: 
     if (lParam != 0) 
      SendMessage((HWND)lParam, MY_COMMAND, wParam, lParam); 
     return 0; 

    case WM_NOTIFY: 
     SendMessage(((NMHDR*)lParam)->hwndFrom, MY_NOTIFY, wParam, lParam); 
     return 0; 

    ... 
    } 

    return DefWindowProc (hwnd, message, wParam, lParam) ; 
} 

LRESULT CALLBACK WndProcButton (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    switch(message) 
    { 
    case MY_COMMAND: 
     ... 
    case MY_NOTIFY: 
     ... 
    } 

    return CallWindowProc(g_wndProcButtonOrigianl, hwnd, message, wParam, lParam); 
}