Тот же идентификатор в динамическом массиве HWND

Я изучаю WinAPI и пытаюсь написать игру Tic Tac Toe. Я использую кнопки, в которых будет отображаться X, O или пустое изображение. Кнопки хранятся в динамическом массиве (HWND). Почему все эти кнопки имеют одинаковый идентификатор?

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. при запуске программы — нижние кнопки позволяют рисовать синие кнопки, верхние кнопки устанавливают количество синих кнопок, но проверяют некоторые радио-кнопки.

3

Решение

Дескрипторы кнопок не равны, но вы не установили для них контрольный идентификатор. Вы можете сделать это, добавив следующее в ваш звонок 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);

Вам придется заменить <your_control_id> часть с уникальным идентификатором для каждой кнопки.

Я думаю, что GetDlgCtrlID() вызов завершается неудачно и поэтому возвращает 0. Подробнее о GetDlgCtrlID() а также CreateWindowEx()

4

Другие решения

Контрольные идентификаторы не назначаются автоматически. Передать идентификатор элемента управления как HMENU параметр для CreateWindow (это упомянуто, хотя и не очень подробно, в документация для CreateWindow).

Конечно, обычный способ их настройки — это просто создать диалог в редакторе ресурсов и присвоить каждому дочернему окну идентификатор элемента управления, который затем используется для поиска каждого дочернего окна. HWND во время выполнения. Но когда вы создаете дочерние окна самостоятельно, у вас есть каждый HWND передать уже, так что вы могли бы просто использовать его напрямую. Это не сложнее в коде, но гораздо проще поддерживать его, например, если вы добавляете больше элементов управления, вам не нужно нигде добавлять больше идентификаторов.

При получении WM_COMMAND сообщение, которое включает идентификатор диалога окна в WPARAMВы можете получить HWND от LPARAMи идентифицируйте ваши дочерние окна таким образом. Увидеть документация для WM_COMMAND.

2

По вопросам рекламы [email protected]