【问题标题】:How do you create a button outside the WM_CREATE message in win32?如何在win32中的WM_CREATE消息之外创建一个按钮?
【发布时间】:2012-11-12 17:08:18
【问题描述】:

我将 c++ 与 win32 和 gdi+ 一起用于图形。
当我在 WM_CREATE 之外初始化一个按钮时,特别是在 WM_TIMER 消息中,在绘制一帧之后,我无法绘制任何其他内容。 这是代码的sn-p:

case WM_TIMER:
    RECT client;
    GetClientRect(hWnd, &client);
    client.bottom-=100; //The bottom hundred pixels are static after I draw the first frame, so I never update them
    if(starting==true)
    {
        starting=false;
        hdc = GetDC(hWnd);
        hdcBuf = CreateCompatibleDC(hdc);
        hdcMem = CreateCompatibleDC(hdcBuf);
        hbmBackBM = CreateCompatibleBitmap(hdc, client.right, client.bottom );
        hbmOldBackBM = (HBITMAP)SelectObject(hdcBuf, hbmBackBM);

        Graphics temp(hdc);
        SolidBrush yelloworange(Color(250,225,65));
        temp.FillRectangle(&yelloworange,0,client.bottom,client.right,100); //Fill the bottom with yellow
        buttons[0]=CreateWindow("button","makereg", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 100, 630, 60, 20, hWnd, HMENU(IDB_MAKEREG), NULL, NULL);
        //buttons[1]=CreateWindow("button","destroyreg", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 100, 670, 80, 20, hWnd, HMENU(IDB_MAKEREG+1), NULL, NULL);
    }
    Graphics g(hdcBuf);

第一部分是双缓冲,我实例化的变量是全局的。我删除了 WM_DESTROY 中的 HDC 和 HBITMAP。开始是一个全局布尔值,被实例化为真。 我在这条 WM_TIMER 消息中完成了我所有的绘图。如果我只注释掉创建按钮的两行,一切都会正常运行。有了它们,它只画出这个 WM_TIMER 中剩下的东西,而不画下一个。所有其他的绘图代码都对 hdcBuf 或 g 完成,然后 hdcBuf 被 BitBlt'd 到 hdc 上。

我尝试在 WM_CREATE 中创建按钮,然后在 WM_TIMER 中显示它,但这导致了同样的问题。我无法在 WM_CREATE 中创建和显示窗口,否则当我用黄色填充底部 100 个像素时它会被覆盖。

有没有办法在 WM_CREATE 和 WM_PAINT 之外创建和显示一个按钮,而不会使其余代码崩溃?

编辑:这是一些在 WM_TIMER 中停止工作的代码:

if(mousex!=uptomousex && mousey!=uptomousey && lbuttondown==true) // this code draws a rectangle between the point where the user begins holding the left mousebutton, and where the mouse is right now.
{
    if(uptomousex-mousex>0 && uptomousey-mousey>0)
        g.DrawRectangle(&(p[0]), mousex, mousey, uptomousex-mousex, uptomousey-mousey);
    else if(uptomousex-mousex<0 && uptomousey-mousey>0)
        g.DrawRectangle((&p[0]), uptomousex, mousey, mousex-uptomousex, uptomousey-mousey);
    else if(uptomousex-mousex>0 && uptomousey-mousey<0)
        g.DrawRectangle((&p[0]), mousex, uptomousey, uptomousex-mousex, mousey-uptomousey);
    else if(uptomousex-mousex<0 && uptomousey-mousey<0)
        g.DrawRectangle(&(p[0]), uptomousex, uptomousey, mousex-uptomousex, mousey-uptomousey);
}

一些全局变量:

bool lbuttondown=false;
float mousex=0;
float mousey=0;
float uptomousex=0;
float uptomousey=0;

WndProc 的其他地方...

case WM_LBUTTONDOWN:
    lbuttondown=true;
    mousex=(float)GET_X_LPARAM(lParam);
    mousey=(float)GET_Y_LPARAM(lParam);
    uptomousex=mousex;
    uptomousey=mousey;
    break;
case WM_MOUSEMOVE:
    if(mousex!=GET_X_LPARAM(lParam) && mousey!=GET_Y_LPARAM(lParam))
    {
        uptomousex=(float)GET_X_LPARAM(lParam);
        uptomousey=(float)GET_Y_LPARAM(lParam);
    }
    break;

【问题讨论】:

  • 您可以随时创建控件,创建控件通常不会阻止“绘图”工作。我认为您需要发布更多代码,尤其是在任何人能够帮助您之前实际上“停止工作”的代码。

标签: c++ winapi gdi+


【解决方案1】:

您在每个计时器调用中创建/获取至少 3 个设备上下文实例,并且您从不删除/释放它们(至少在您发布的示例中),因此您以破坏整个 GDI 系统而告终也就不足为奇了.

对于每个 GetDC() 调用,都应该调用 ReleaseDC(),

对于每个 CreateCompatibleDC() 调用,都应该调用 DeleteObject()。

【讨论】:

  • 我在 WM_DESTROY 中删除了它们。它们仅在第一次计时器调用中创建,因为在那之后启动是错误的,并且 if 语句会跳过整个代码块。
  • 不,B 代表按钮。它只是#define IDB_MAKEREG 501
  • 来自文档:对于子窗口,hMenu 指定子窗口标识符,对话框控件用于通知其父级事件的整数值。应用程序确定子窗口标识符; 对于具有相同父窗口的所有子窗口,它必须是唯一的
  • 糟糕。然而,事实并非如此。显然我很幸运有两个错误。如果我只制作一个按钮或将第二个 IDB_MAKEREG 更改为 IDB_MAKEREG+1,它仍然不起作用。我将更改代码以反映它。
  • 尝试将计时器的间隔加倍,以确保不是计时问题。
【解决方案2】:

我还没有弄清楚为什么会这样,但我创建了一个简单的补丁:我自己的按钮类,我将在这里分享:

class button
{
public:
    int x;
    int y;
    int width;
    int height;
    string text;
    void (*func)(short);
    button(int px, int py, int w, int h, string txt, void (*f)(short))
    {
        x=px;
        y=py;
        width=w;
        height=h;
        text=txt;
        func=*f;
    }
};

然后,有一个全局的按钮向量,allbuttons,在 WM_LBUTTONUP 消息中,我循环遍历所有按钮并检查点击是否在按钮中,如果是,我调用 func.

它更简单、更灵活,而且确实有效。然而,图形更糟糕,我仍然想找出为什么 windows 按钮功能失调,只是出于好奇。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多