限制为64 ownerdraw创建窗口按钮

时间:2009-07-08 16:48:50

标签: showmodaldialog ownerdrawn

我想创建一个由256个彩色按钮组成的数组,所有者将扩展样式绘制到使用visual studio对话框设计工具创建的对话框中。我在对话框过程中为WM_INITDIALOG消息处理程序添加了一个循环来执行此操作:

for (i=0; i<=255; i++)
{

int xp, yp;
HWND status;

xp = rect_pos.left+16*(i%16);
yp = rect_pos.top+16*(i>>4);
status = CreateWindow (
    TEXT("button"),
    "\0",
    WS_CHILD|WS_VISIBLE|BS_OWNERDRAW|BS_PUSHBUTTON,
    xp,
    yp,
    15,
    15,
    hDlg,
    (HMENU) 5000+i,     // id used to report events
    hInst,
    NULL
);

if (status == NULL)
    xp =7;
}

我为WM_CTLCOLORBTN消息添加了一个消息处理程序。

case WM_CTLCOLORBTN:
{   
    int     zz;

    zz = GetWindowLong ((HWND) lParam, GWL_ID); // window identifier
    zz -= 5000;
    if ((zz >= 0) && (zz <= 255))
    {
        HBRUSH BS;

        SetTextColor ((HDC) wParam, Collector.Color);
        SetBkColor ((HDC) wParam,   Collector.Color); 

        return ((LRESULT) Collector.Brush);       

    }
    break;
}

或多或少的工作但只显示前64个按钮。我打算使用不同的画笔为每个按钮上色,但对于调试瞳孔,我替换了一个定义良好的画笔。我已经调试了代码,并且对每个按钮的x / y坐标都是正确的,并且hMenu createwindow调用中提供的ID是正确的。我在WM_CTLCOLORBTN处理程序中看到所有256个按钮都被着色。我包括一个检查,以确保createwindow调用不会返回失败(NULL)。我可以通过在createwindow调用上交换x / y参数来获得4行16个按钮或4列16个按钮。

如果我从createwindow调用中删除了BS_OWNERDRAW位,则会绘制所有256个按钮。

就好像BS_OWNERDRAW有64个按钮的限制: - (

非常感谢任何帮助!

TIA,迈克

2 个答案:

答案 0 :(得分:1)

您是否将 WM_DRAWITEM 消息与 BS_OWNERDRAW 样式一起处理?

在您的情况下,对我来说,使用 BS_OWNERDRAW 样式时会显示任何按钮,而 BS_PUSHBUTTON 设置时会显示任何按钮。

如以下指向 BS_OWNERDRAW 文档的链接所述,您需要处理 WM_DRAWITEM 并避免指定任何其他 BS _ 按钮样式。

Button Styles from MSDN

同样奇怪的是,可能会收到 WM_CTLCOLORBUTTON 消息,然后忽略包含 BS_PUSHBUTTON 样式的按钮。请查看以下链接以获取该窗口消息的文档。

WM_CTLCOLORBUTTON from MSDN

从我在您的代码段中看到的内容,您很可能会想要执行以下操作:

  1. 创建子按钮时设置BS_OWNERDRAW。
  2. 在对话框上处理WM_DRAWITEM并以正确的状态绘制按钮。请注意,您不必处理WM_CTLCOLORBUTTON,只需使用画笔和字体,并根据需要在WM_DRAWITEM处理程序中修改DC。
  3. 此外,根据您的应用程序,您可能会受益于制作自己的窗口类来表示自己的按钮网格,并只是绘制项目的味道。如果您只是显示内部状态而不是真正寻找用户来管理或与按钮网格交互,那么这是首选。

答案 1 :(得分:0)

感谢所有给予建议和帮助的人。我现在对此工作让我满意。我已经成功地为按钮着色,并且如果选择了它们或者如果它们具有输入焦点,则用黑色轮廓包围它们。我将在下面添加一些代码片段来显示事物的最终状态,但这里是概要。首先,我相信我的系统中有一些遗留代码,它使所有者绘制的按钮响应WM_CTLCOLORBTN创建的第一个子64按钮。其次,我认为唯一需要做的就是创建按钮,正确响应WM_DRAWITEM和WM_COMMAND / BN_CLICKED消息。

以下是我的对话框处理程序中的代码段。

在WM_INITDIALOG代码中 - 创建按钮

        for (i=0; i<=255; i++)
        {
            int xp, yp;
            HWND status;

            xp = rect_pos.left+16*(i&0x0F);
            yp = rect_pos.top+16*(i>>4);

            status = CreateWindow 
                (
                TEXT("button"),
                "\0",
                WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_OWNERDRAW,
                xp,
                yp,
                15,
                15,
                hDlg,
                (HMENU) (5000+i),                       // id used to report events
                hInst,
                NULL
                );

            if (status == NULL)
                xp =7;


            SetFocus (status);

        }

回复WM_DRAWITEM消息

case WM_DRAWITEM:                           // Owner drawn botton
    {
        LPDRAWITEMSTRUCT lpDrawItem;
        HBRUSH  BS, BS_Old;
        HPEN    PN_Old;
        int     sz=15;
        int     cntl;

        cntl =  LOWORD (wParam) - 5000;

        lpDrawItem = (LPDRAWITEMSTRUCT) lParam;

        if (lpDrawItem->CtlType != ODT_BUTTON)
            return FALSE;

        BS = CreateSolidBrush (ColorRef[cntl]);

        if (lpDrawItem->itemState & (ODS_SELECTED | ODS_FOCUS))
        {
            sz = 14;
            PN_Old = (HPEN) SelectObject(lpDrawItem->hDC, GetStockObject(BLACK_PEN));
        }
        else
            PN_Old = (HPEN) SelectObject(lpDrawItem->hDC, GetStockObject(NULL_PEN));

        BS_Old = (HBRUSH) SelectObject(lpDrawItem->hDC, BS);
        Rectangle (lpDrawItem->hDC, 0, 0, sz, sz);
        SelectObject(lpDrawItem->hDC, PN_Old);
        SelectObject(lpDrawItem->hDC, BS_Old);
        DeleteObject (BS);

        return true;
    }

最后在WM_COMMAND代码中

    if (HIWORD(wParam) == BN_CLICKED) 
    { 
        if ((LOWORD(wParam) >= 5000) && (LOWORD(wParam) <=5255))
        {

            Color[0] = ColorRef[LOWORD(wParam)-5000] & 0xFF;
            Color[1] = (ColorRef[LOWORD(wParam)-5000] >> 16) & 0xFF;
            Color[2] = (ColorRef[LOWORD(wParam)-5000] >> 8 ) & 0xFF;

            InvalidateRect (hDlg, NULL, TRUE);

            goto Set_Color;
        } 
     }