HWND动态数组中的相同ID。

时间:2022-04-28 02:30:30

I'm learning WinAPI and trying to write a Tic Tac Toe game. I`m using buttons in which will be displayed X,O or empty image.Buttons stored in a dynamic array(HWND).Why all this Buttons have the same ID?

我正在学习WinAPI,并尝试写一个Tic Tac脚趾游戏。我使用的按钮将显示X,O或空图像。在动态数组中存储的按钮(HWND)。为什么所有这些按钮都有相同的ID?

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

MessageBox appears!, why. Please help.

对话框出现!,为什么。请帮助。

//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));
}

The Project(VS2008) is here : http://www.filehosting.org/file/details/372626/XXXOOO.rar

项目(VS2008)在这里:http://www.filehost.org/file/details/3726/xxxooo.rar。

P.S.when execute the program - lower Button allow to draw in a blue buttons,upper button set the amount of blue buttons, but check some radioBtn.

注:在执行程序时,按下按钮允许绘制蓝色按钮,上面的按钮设置蓝色按钮的数量,但是检查一些radioBtn。

2 个解决方案

#1


4  

The button handles are not equal, but you haven't set a control id for them. You could do this by adding the following to your call to CreateWindowEx:

按钮句柄不相等,但您还没有为它们设置一个控制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);

You will have to replace the <your_control_id> part with a unique id for every button.

您将不得不使用每个按钮的惟一id替换 部分。

My guess is that the GetDlgCtrlID() call fails and therefore returns 0. Read more about GetDlgCtrlID() and CreateWindowEx()

我的猜测是GetDlgCtrlID()调用失败,因此返回0。阅读更多有关GetDlgCtrlID()和CreateWindowEx()的内容

#2


2  

Control IDs are not assigned automatically. Pass the control ID in as the HMENU parameter to CreateWindow (this is mentioned, though not in any great detail, in the documentation for CreateWindow).

没有自动分配控制id。将控制ID作为HMENU参数传递到CreateWindow(在CreateWindow的文档中,虽然没有详细说明)。

The usual way to set them up, of course, is simply to create the dialog in the resource editor, and give each child window a control ID, which you then use to find each child window's HWND at runtime. But when you're creating the child windows yourself, you have each HWND to hand already, so you might as well just use it directly. This is no harder to code, but much easier to keep on top of - e.g., if you add more controls, you don't need to add more IDs anywhere.

当然,设置它们的通常方法是在资源编辑器中创建对话框,并给每个子窗口一个控件ID,然后在运行时使用它来查找每个子窗口的HWND。但是当您自己创建子窗口时,您已经拥有了每个HWND,所以您也可以直接使用它。这对代码来说并不难,但是要保持在上面很容易——例如,如果你添加了更多的控件,你就不需要在任何地方添加更多的id。

When receiving a WM_COMMAND message, which includes the window's dialog ID in the WPARAM, you can get the HWND from the LPARAM, and identify your child windows that way instead. See the documentation for WM_COMMAND.

当收到WM_COMMAND消息(包括WPARAM中的窗口的对话框ID)时,您可以从LPARAM获得HWND,并以这种方式识别您的子窗口。参见WM_COMMAND的文档。

#1


4  

The button handles are not equal, but you haven't set a control id for them. You could do this by adding the following to your call to CreateWindowEx:

按钮句柄不相等,但您还没有为它们设置一个控制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);

You will have to replace the <your_control_id> part with a unique id for every button.

您将不得不使用每个按钮的惟一id替换 部分。

My guess is that the GetDlgCtrlID() call fails and therefore returns 0. Read more about GetDlgCtrlID() and CreateWindowEx()

我的猜测是GetDlgCtrlID()调用失败,因此返回0。阅读更多有关GetDlgCtrlID()和CreateWindowEx()的内容

#2


2  

Control IDs are not assigned automatically. Pass the control ID in as the HMENU parameter to CreateWindow (this is mentioned, though not in any great detail, in the documentation for CreateWindow).

没有自动分配控制id。将控制ID作为HMENU参数传递到CreateWindow(在CreateWindow的文档中,虽然没有详细说明)。

The usual way to set them up, of course, is simply to create the dialog in the resource editor, and give each child window a control ID, which you then use to find each child window's HWND at runtime. But when you're creating the child windows yourself, you have each HWND to hand already, so you might as well just use it directly. This is no harder to code, but much easier to keep on top of - e.g., if you add more controls, you don't need to add more IDs anywhere.

当然,设置它们的通常方法是在资源编辑器中创建对话框,并给每个子窗口一个控件ID,然后在运行时使用它来查找每个子窗口的HWND。但是当您自己创建子窗口时,您已经拥有了每个HWND,所以您也可以直接使用它。这对代码来说并不难,但是要保持在上面很容易——例如,如果你添加了更多的控件,你就不需要在任何地方添加更多的id。

When receiving a WM_COMMAND message, which includes the window's dialog ID in the WPARAM, you can get the HWND from the LPARAM, and identify your child windows that way instead. See the documentation for WM_COMMAND.

当收到WM_COMMAND消息(包括WPARAM中的窗口的对话框ID)时,您可以从LPARAM获得HWND,并以这种方式识别您的子窗口。参见WM_COMMAND的文档。