2012-09-05 25 views
3

我正在學習WinAPI並嘗試編寫一個Tic Tac Toe遊戲。我使用的按鈕將顯示X,O或空圖像。按鈕存儲在一個動態數組(HWND)。爲什麼所有這些按鈕都有相同的ID?HWND動態數組中的相同ID

if(GetDlgCtrlID(hBtns[0][0]) == GetDlgCtrlID(hBtns[0][1])) 
    MessageBox(hWndDlg,_T("TheSame"),_T(""),NULL); 

MessageBox出現!,爲什麼。請幫忙。

//KA_SHAG 
//Miwa_Mikitin 
//XXXOOO 
#include<windows.h> 
#include<tchar.h> 
#include"resource.h" 

//Main Proc 
BOOL CALLBACK DialogProc(HWND hWndDlg,UINT message,WPARAM wParam,LPARAM lParam); 
//EnumChildProc 
BOOL CALLBACK DisableEnableButtons(HWND hwnd,LPARAM lParam); 

HWND** hBtns;//Global Dynamic Array of Buttons 
int size = 150;//Size of Side of field, Button Size = size/nButtons 

//BITMAPS 
HBITMAP hBmpX,hBmpO,hBmpNone; 
///////// 

void CreateButtons(HWND hWndDlg,int nBtnsOld,int nBtnsNew); 
void LoadBitmaps(); 


INT WINAPI WinMain(HINSTANCE hIns,HINSTANCE hPrevIns,LPSTR cmdLine,INT nShowCmd) 
{ 
    HWND hWndDlg = CreateDialog(hIns,MAKEINTRESOURCE(IDD_DIALOG1),NULL,DialogProc); 

    MSG msg; 
    ShowWindow(hWndDlg,1); 

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

    return msg.wParam; 
} 

BOOL CALLBACK DialogProc(HWND hWndDlg,UINT message,WPARAM wParam,LPARAM lParam) 
{ 
    HINSTANCE hIns = GetModuleHandle(0);    
    static int nBtnsOld = 5;//intitial N of Buttons on a row|col 
    static int nBtnsNew;//next update N of Buttons on a row|col 
    static BOOL isPlaying = false; 
    static BOOL isMyMove = true; 

    switch(message) 
    { 
    case WM_INITDIALOG: 
     {  
      LoadBitmaps(); 
      CreateButtons(hWndDlg,nBtnsOld,nBtnsOld); 
     } 
     return true; 

    case WM_COMMAND: 
     if(HIWORD(wParam) == BN_CLICKED) 
     { 
      //Resize the Button field 
      if(LOWORD(wParam) == IDC_BTNSETSIZE) 
      {  
       //Determine wich RadioBtn is Checked 
       if(IsDlgButtonChecked(hWndDlg,IDC_RADIO33)) 
        nBtnsNew = 3;//set new nBtns 
       if(IsDlgButtonChecked(hWndDlg,IDC_RADIO44)) 
        nBtnsNew = 4;//set new nBtns 
       if(IsDlgButtonChecked(hWndDlg,IDC_RADIO55)) 
        nBtnsNew = 5;//set new nBtns 
       /////////////////////////////////////////// 
       //If no difference than ignore 
       //else Create new Array of Btns 
       if(nBtnsOld != nBtnsNew) 
       { 
        CreateButtons(hWndDlg,nBtnsOld,nBtnsNew); 
        nBtnsOld = nBtnsNew; 
       } 
       ///////////////////////////////////////// 
       return true; 
      } 
      if(LOWORD(wParam) == IDC_BTNBEGIN) 
      { 
       //Enum Buttons,CheckBox,RadioBtns 
       //then Disable or Enable them depending on isPlaying var 
       //if TRUE - ENABLE 
       //else Disable 
       EnumChildWindows(hWndDlg,DisableEnableButtons,isPlaying); 
       //switch isPlaying) 
       isPlaying = !isPlaying; 
       //switch begin Button Text 
       if(isPlaying) 
        SetWindowText(GetDlgItem(hWndDlg,IDC_BTNBEGIN),_T("Закінчити гру")); 
       else 
        SetWindowText(GetDlgItem(hWndDlg,IDC_BTNBEGIN),_T("Почати гру")); 
       ///////////////////////////////////////////////////////////////////// 
       return true; 
      } 
      //When Playing 
      if(isPlaying) 
      { 
       //Determine HWND of Pressed Btn 
       HWND pressedBtn = GetDlgItem(hWndDlg,LOWORD(wParam)); 
       HBITMAP propBmp; 
       if(isMyMove) 
        propBmp = hBmpX; 
       else 
        propBmp = hBmpO; 
       //Change BMP 
       SendMessage(pressedBtn, 
        BM_SETIMAGE,IMAGE_BITMAP, 
        (LPARAM)propBmp); 
       //WHY??? 
       if(GetDlgCtrlID(hBtns[0][0]) == GetDlgCtrlID(hBtns[0][1])) 
        MessageBox(hWndDlg,_T("TheSame"),_T(""),NULL); 

       return true; 
      } 
     } 
     return true; 
    case WM_CLOSE: 
     DestroyWindow(hWndDlg); 
     PostQuitMessage(0); 
     return TRUE; 
    } 

    return FALSE; 
} 

void CreateButtons(HWND hWndDlg,int nBtnsOld,int nBtnsNew) 
{ 

    HINSTANCE hIns = GetModuleHandle(0);//main instance 

    //Destroy Buttons 
    if(hBtns) 
    { 
     for(int i=0;i<nBtnsOld;i++) 
      for(int j=0;j<nBtnsOld;j++) 
       DestroyWindow(hBtns[i][j]); 
     ////////////////////////////////  
     //Free memory 
     for(int n=0;n<nBtnsOld;n++) 
      delete[]hBtns[n]; 
     delete[]hBtns; 
    } 
    ///////////////////////////////// 
    //Allocate new memory 
    hBtns = new HWND*[nBtnsNew]; 
    for(int n=0;n<nBtnsNew;n++) 
     hBtns[n] = new HWND[nBtnsNew]; 
    //////////////////////////////// 
    int x =0;//offset x 
    int y =0;//offset y 
    //tchar[] for diff name s of btns 

    //Create Buttons & assign to hBtns Array 
    for(int i=0;i<nBtnsNew;i++) 
    { 
     for(int j=0;j<nBtnsNew;j++) 
     { 

      hBtns[i][j] = CreateWindowEx(
       NULL,_T("Button"), 
       NULL, 
       WS_CHILD | WS_VISIBLE | BS_BITMAP | BS_NOTIFY , 
       x,y,size/nBtnsNew,size/nBtnsNew, 
       hWndDlg,NULL, 
       hIns,NULL); 
      //Set Default Image On Btns 
      SendMessage(hBtns[i][j],BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)hBmpNone); 

      x+=size/nBtnsNew; 

     } 
     y+=size/nBtnsNew; 
     x=0; 
    } 
} 

BOOL CALLBACK DisableEnableButtons(HWND hwnd,LPARAM lParam) 
{ 
    //Lparam is a BOOL if true Button will be Enabled 
    //else Buttons will be Disabled 
    if(GetDlgCtrlID(hwnd) == IDC_RADIO33 || 
     GetDlgCtrlID(hwnd) == IDC_RADIO44 || 
     GetDlgCtrlID(hwnd) == IDC_RADIO55 || 
     GetDlgCtrlID(hwnd) == IDC_CHECKMOVE || 
     GetDlgCtrlID(hwnd) == IDC_BTNSETSIZE) 
     EnableWindow(hwnd,lParam);//<---lParam is BOOL 

    return TRUE; 
} 

//BOOL CALLBACK DrawBmpOnBtn(HWND hwnd,LPARAM lParam) 
//{ 
// 
// SendMessage(hwnd,BM_SETIMAGE, 
// return TRUE; 
//} 

void LoadBitmaps() 
{ 
    HINSTANCE hIns = GetModuleHandle(0);//main instance 

    hBmpX = LoadBitmap(hIns,MAKEINTRESOURCE(IDB_BMP_X)); 
    hBmpO = LoadBitmap(hIns,MAKEINTRESOURCE(IDB_BMP_O)); 
    hBmpNone = LoadBitmap(hIns,MAKEINTRESOURCE(IDB_BMP_NONE)); 
} 

項目(VS2008)是在這裏:http://www.filehosting.org/file/details/372626/XXXOOO.rar

P.S.when執行程序 - 下部按鈕允許在一個藍色的按鈕來繪製,上按鈕設置藍色按鈕的數量,但檢查一些radioBtn。

+1

只是因爲你從來沒有設置ID。您在創建按鈕的CreateWindowEx()調用中爲hMenu參數傳遞NULL。 –

+2

我不得不不同意這個問題的結束。我相信這不是第一次也不是最後一次有人沒有注意到HMENU參數有第二個隱藏目的。 –

+1

我同意@MarkRansom,我沒有看到任何理由將此問題視爲「過於本地化」。 – Cyclonecode

回答

4

按鈕手柄不相同,但您沒有爲它們設置控件ID。您可以通過添加以下到您的來電CreateWindowEx做到這一點:

hBtns[i][j] = CreateWindowEx(
       NULL, _T("Button"), 
       NULL, 
       WS_CHILD | WS_VISIBLE | BS_BITMAP | BS_NOTIFY, 
       x, y, size/nBtnsNew, size/nBtnsNew, 
       hWndDlg, 
       (HMENU)<your_control_id>, 
       hIns, NULL); 

你將不得不與每個按鈕一個唯一的ID來代替<your_control_id>部分。

我的猜測是,GetDlgCtrlID()調用失敗,因此返回0瞭解更多關於GetDlgCtrlID()CreateWindowEx()

2

控件ID不會自動分配。將控制ID作爲HMENU參數傳遞給CreateWindow(這裏提到,儘管沒有詳細說明,但在the documentation for CreateWindow中)。

設置它們的常用方法當然是簡單地在資源編輯器中創建對話框,併爲每個子窗口提供一個控件ID,然後在運行時用它來查找每個子窗口的HWND。但是當你自己創建子窗口時,你已經有了每個HWND,所以你可以直接使用它。這並不困難,但更容易保持 - 例如,如果添加更多控件,則無需在任何位置添加更多ID。

當接收到一個WM_COMMAND消息,其中包括在WPARAM窗口的對話框ID,您可以從LPARAMHWND,並找出你的子窗口這種方式來代替。見the documentation for WM_COMMAND