2014-01-05 80 views
0
ATOM MyRegisterChildClass(void) 
{ 
    WNDCLASSEX wcex = {0}; 
    wcex.cbSize = sizeof(WNDCLASSEX); 
    wcex.lpfnWndProc = ChildProc; 
    wcex.hInstance = hInst; 
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 8); 
    wcex.lpszClassName = ChildClassName; 
    return RegisterClassEx(&wcex); 
} 
static HFONT newFont; 
static HWND hChild[9]; 
unsigned char k[9] = {0}; 
char text[] = {' ', 'X', '0'}; 
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    int i; 
    static int sx, sy; 
    switch (message) 
    { 
    case WM_CREATE: 
     MyRegisterChildClass(); 
     for(i = 0; i < 9; i++) 
      hChild[i] = CreateWindow(ChildClassName, NULL, WS_CHILD | 
      WS_DLGFRAME | WS_VISIBLE, 0, 0, 0, 0, hWnd, NULL, hInst, NULL); 
     break; 
    case WM_SIZE: 
     if(wParam == SIZE_MINIMIZED) 
      break; 
     sx = LOWORD(lParam)/3; 
     sy = HIWORD(lParam)/3; 
     if(newFont) 
      DeleteObject(newFont); 
     newFont = CreateFont(min(sx, sy), 0, 0, 0, FW_NORMAL, 0, 0, 0, 
      DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, 
      DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Arial"); 
     for(i = 0; i < 9; i++) 
     { 
      MoveWindow(hChild[i], (i%3)*sx, (i/3)*sy, sx, sy, TRUE); 
      UpdateWindow(hChild[i]); 
     } 
     break; 
    case WM_COMMAND: 
     switch(LOWORD(wParam)) 
     { 
     case ID_NEW: 
      for(i = 0; i < 9; i++) 
      { 
       k[i] = 0; 
       InvalidateRect(hChild[i], NULL, TRUE); 
       UpdateWindow(hChild[i]); 
      } 
      break; 
     case IDM_EXIT: 
      DestroyWindow(hWnd); 
      break; 
     case IDM_ABOUT: 
      DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); 
      break; 
     default: 
      return DefWindowProc(hWnd, message, wParam, lParam); 
     } 
     break; 


    case WM_DESTROY: 
     PostQuitMessage(0); 
     break; 
    default: 
     return DefWindowProc(hWnd, message, wParam, lParam); 
    } 
    return 0; 
} 
LRESULT CALLBACK ChildProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
PAINTSTRUCT ps; 
HDC hDC; 
RECT rt; 
int s, i; 
char *ch; 
switch(message) 
{ 
case WM_LBUTTONDOWN: 
    for(i = 0; hWnd != hChild[i]; i++); 
    if(k[i]) 
     break; 
    else 
     k[i] = 1; 
    InvalidateRect(hWnd, NULL, TRUE); 
    UpdateWindow(hWnd); 
    srand(lParam); 
    for(i = s = 0; i < 9; i++) 
     if(k[i]) 
      s++; 
    if(s == 9) 
     MessageBox(hWnd, L"...",L"...", MB_OK|MB_ICONQUESTION); 
    else 
    { 
     while(true) 
     { 
      s = rand()*9/(RAND_MAX+1); 
      if(k[s]) 
       continue; 
      k[s] = 2; 
      InvalidateRect(hChild[s], NULL, TRUE); 
      UpdateWindow(hChild[s]); 
      break; 
     } 
    } 
    break; 
case WM_PAINT: 
    for(i = 0; hWnd != hChild[i]; i++); 
    if(k[i]) 
    { 
     ch = text+k[i]; 
     hDC = BeginPaint(hWnd, &ps); 
     GetClientRect(hWnd, &rt); 
     SelectObject(hDC, newFont); 
     DrawTextA(hDC, ch, 1, &rt, DT_SINGLELINE | DT_CENTER | DT_VCENTER); 
     EndPaint(hWnd, &ps); 
    } 
    else 
     DefWindowProc(hWnd, message, wParam, lParam); 
    break; 
default: 
    DefWindowProc(hWnd, message, wParam, lParam); 
} 
return 0; 
} 

我正在嘗試使用井字遊戲。這是我手動編寫的代碼(這裏沒有由Visual Studio生成的標準代碼)。我製作了9個兒童窗戶。 此代碼會運行,但它不會顯示子窗口,並且在按下鼠標左鍵時不會反應。在調試器的幫助下,我看到消息WM_LBUTTONDOWN和WM_PAINT從不發送給ChildProc函數。 有什麼問題?子窗口不顯示

回答

3
for(i = 0; i < 9; i++) 
     hChild[i] = CreateWindow(ChildClassName, NULL, WS_CHILD | 
     WS_DLGFRAME | WS_VISIBLE, 0, 0, 0, 0, hWnd, NULL, hInst, NULL); 

你犯了一個傳統的錯誤,你一味地希望winapi函數能成功。這是空閒的希望,CreateWindow()失敗並返回NULL。你也可以用調試器看到的東西,你會看到hChild數組只包含空值。 始終編寫代碼的防守,在絕對最低使用斷言()來備份你的假設:

for(i = 0; i < 9; i++) { 
     hChild[i] = CreateWindow(ChildClassName, ...); 
     assert(hChild[i]); 
    } 

大量的代碼中的其他地方,你應該這樣做。您現在必須在診斷故障時遇到麻煩。

實際的錯誤位於ChildProc():

default: 
    DefWindowProc(hWnd, message, wParam, lParam); 
} 
return 0; 

或者換句話說,它總是 0,這是不行的,你應該只當你處理的消息返回值。您沒有按消息處理。再次使用調試器並在ChildProc的switch()語句中設置一個斷點。您將看到第一條消息被錯誤處理,WM_NCCREATE。這要求您返回TRUE以繼續創建窗口。你不這樣做,你返回FALSE。所以這是窗口創建的快速結束。你必須必須返回DefWindowProc()的值。修復:

default: 
    return DefWindowProc(hWnd, message, wParam, lParam); 

請注意,您還在WndProc()中使用WM_CREATE消息玩一個危險的遊戲。返回0意外工作,你應該總是將消息傳遞給DefWindowProc(),因爲你實際上並沒有處理WM_CREATE,你只是將它用作通知。