i'm owner draw some controls.
here what i use for a button:

case WM_DRAWITEM:
            {
                DRAWITEMSTRUCT *test=(DRAWITEMSTRUCT*) lParam;
                HIMAGELIST imlIcon=ImageList_Create(inst->imgtest.width(),inst->imgtest.height(),ILC_COLOR,1,1);
                ImageList_Add(imlIcon,inst->imgtest,NULL);
                HTHEME hTheme = OpenThemeData(inst->hwnd, L"BUTTON");

                //fill the background with button face color
                FillRect(test->hDC, &test->rcItem,(HBRUSH) GetSysColor(COLOR_BTNFACE));

                if ( test->itemState & ODS_SELECTED) // If it is pressed
                {
                    DrawEdge(test->hDC,&test->rcItem,EDGE_SUNKEN,BF_RECT); // Draw a sunken face
                }
                else if ( test->itemState & ODS_DISABLED)
                {
                    DrawThemeBackground(hTheme, test->hDC, BP_PUSHBUTTON, PBS_DISABLED, &test->rcItem, 0);
                }
                else
                {
                    DrawEdge(test->hDC, &test->rcItem,EDGE_RAISED,BF_RECT); // Draw a raised face
                }
                //add the transparent image to the button


                if ( test->itemState & ODS_DISABLED)
                {
                    DrawThemeIcon(hTheme, test->hDC, BP_PUSHBUTTON, PBS_DISABLED,&test->rcItem,imlIcon,0);
                    DrawThemeText(hTheme, test->hDC, BP_PUSHBUTTON, PBS_DISABLED,(LPCWSTR) inst->strCaption.c_str(),-1,DT_LEFT|DT_HIDEPREFIX,0,&test->rcItem);
                }
                else
                {
                    TransparentBlt(test->hDC,0,0,inst->imgtest.width(),inst->imgtest.height(),inst->imgtest,0,0,inst->imgtest.width(),inst->imgtest.height(),GetPixel(inst->imgtest,0,0));
                    SetTextColor(test->hDC,inst->clrTextColor);
                    SetBkMode(test->hDC,TRANSPARENT);//text background transparent
                    DrawText(test->hDC,inst->strCaption.c_str(),-1,&test->rcItem,DT_LEFT);
                }
                //draw the caption



                //draw the focus rectangle
                HPEN pen = CreatePen(PS_DOT,1,RGB(0,0,0));//these is the must close to the rectangle focus style
                SelectObject(test->hDC,pen);
                SelectObject(test->hDC,GetStockObject(NULL_BRUSH));//the rectangle will be transparent
                if ( (test->itemState & ODS_FOCUS )) // If the button is focused
                {
                    int iChange = 3;
                    test->rcItem.top += iChange;
                    test->rcItem.left += iChange;
                    test->rcItem.right -= iChange;
                    test->rcItem.bottom -= iChange;
                    Rectangle(test->hDC, test->rcItem.left, test->rcItem.top, test->rcItem.right, test->rcItem.bottom);
                }
                CloseThemeData(hTheme);
                ImageList_Destroy(imlIcon);
            }
            break;

i see 1 problem with these 2 lines:

DrawThemeIcon(hTheme, test->hDC, BP_PUSHBUTTON, PBS_DISABLED,&test->rcItem,imlIcon,0);
                    DrawThemeText(hTheme, test->hDC, BP_PUSHBUTTON, PBS_DISABLED,(LPCWSTR) inst->strCaption.c_str(),-1,DT_LEFT|DT_HIDEPREFIX,0,&test->rcItem);

1 - the icon isn't drawed black and white. i only see a black rectangle with control size;
2 - the text is drawed, but why i see chinese characteres?

If you are seeing weird characters, it's most likely because of:

(LPCWSTR) inst->strCaption.c_str()

Seeing this makes me believe that your strCaption is an std::string and NOT std::wstring.

This cast is therefore an illegal cast. What makes you think you can just cast a const char* to a const wchar_t*?

If you want to convert them, you either need to do:

std::wstring str = std::wstring(strCaption.begin(), strCaption.end());

and then: str.c_str() would be the argument to DrawThemeText.

The above conversion will ONLY work if all the characters in strCaption are in the ASCII table.. Even then, the above is NOT recommended..

The proper way is to convert it using:

void NarrowToWideChar(const std::string &input, std::wstring& output)
{
    output.clear();
    output.resize(MultiByteToWideChar(CP_ACP, 0, &input[0], -1, NULL, 0) + 1);
    MultiByteToWideChar(CP_ACP, 0, &input[0], -1, &output[0], output.size() - 1);
}

The above code does NOT have error checking.. For example, checking whether the conversion was a success or whether the length of "output" is > 0, etc.. That, I leave up to you.

---------------------------

In the future, pay attention to the documentation for functions you use:

https://msdn.microsoft.com/en-us/library/windows/desktop/bb773312%28v=vs.85%29.aspx

states:

Examples

DrawThemeText uses parameters similar to the Win32 DrawText function, but with a few differences. One of the most notable is support for wide-character strings. Therefore, non-wide strings must be converted to wide strings, as in the following example.

Security Warning: Using MultiByteToWideChar incorrectly can compromise the security of your application. Ensure that when creating wide-character buffers they are large enough to accommodate the size of the string in wide characters, not in bytes.

It gives an example of how to use it and how to do the conversion as well..

I very strongly recommend that you read that example!

Edited 1 Year Ago by triumphost

Comments
thanks for all
This article has been dead for over six months. Start a new discussion instead.