所有者绘制组合下拉列表不保留aero样式。 [英] Owner draw combo drop down list does not retain the aero style.

查看:95
本文介绍了所有者绘制组合下拉列表不保留aero样式。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

即使在绘制了所有者之后,是否有可能获得aero样式组合下拉列表?我发现一些网站建议通过加载UTHEME DLL来使用comctl 6版本。作为替代方案,也可以通过子类化和处理WM_PAINT消息来完成。但是不能保证它可以与更高版本的Windows一起使用。

我很困惑,这可能是处理这个问题的更好方法。请帮助!!



[更新]



大家好,首先非常感谢你们解决问题的时间和兴趣。我想我会改进我的问题。

我有一个UI设计,它有许多droplist样式的CB。因为我需要一些GDI绘图(对于分隔符和灰色的),我不得不让其中一个所有者绘制。现在我观察到被绘制的CB的外观已经改变了(白色背景看起来类似于简单的CB)。经过一番搜索后,我最终阅读了这篇文章:

http://microsoft.public.win32.programmer.ui.narkive.com/fHHS7f60/drop-down-list-with-cbs-dropdownlist-cbs-ownerdrawvariable- in-vista [ ^ ]

所以我开始通过子类化CB proc并通过从UXTHEME DLL加载API来绘制组合框。现在我认为它非常混乱。我需要处理每个事件(WM_OUSEMOVE,WM_MOUSEHOVER ....)以及应用程序最小化或调整大小等时发送的事件。否则CB将返回简单样式CB。

我试图在WM_DRAWITEM消息中绘制。但它不起作用。

我错过了一些非常基本的东西,或者有更简单的方法吗?

Is it possible to get the aero style combo drop down list even after making it owner drawn? I found a few sites that suggested using the comctl 6 version by loading the UTHEME DLL. As an alternate, it can also be done by sub classing and processing the WM_PAINT message. But there is no guarantee that it may work with later versions of windows.
I am confused as to which could be a better way of handling this problem. Please help!!

[Update]

Hi guys, first of all thanks a lot for your time and interest in solving the problem. I thought I will improve my question.
I have a UI design which has many droplist style CBs. I had to make one of them owner drawn since i needed some GDI drawing(for seperators and grayng out). Now i observed that the look of the CB which was made owner drawn has changed(White background looking similar to simple CB). After some searching i ended up reading this article:
http://microsoft.public.win32.programmer.ui.narkive.com/fHHS7f60/drop-down-list-with-cbs-dropdownlist-cbs-ownerdrawvariable-in-vista[^]
So i started by sub classing the CB proc and painted the combo box by loading the APIs from UXTHEME DLL. Now i think its very messy. I need to handle every event (WM_OUSEMOVE, WM_MOUSEHOVER....) and also events sent when the app is minimized or resized etc. Or else the CB turns back to simple style CB.
I tried to draw at the WM_DRAWITEM message. But it does not work.
Am i missing something very basic here or is there a simpler way to do this?

推荐答案

正如所承诺的那样。在Windows7下使用gcc 4.7.2构建。哈!代码在下周两岁了 - 哦,从那以后我学到了什么。 :笑:



main.cpp

As promised. Built with gcc 4.7.2 under Windows7. Hah! the code's two years old next week - oh what I've learned since then. :laugh:

main.cpp
#define WIN32_LEAN_AND_MEAN
#define UNICODE 1

#include <windows.h>
#include <commctrl.h>

#include "resource.h"

HINSTANCE hInst;

#define XBITMAP 48
#define YBITMAP 48

#define BUFFER MAX_PATH

HBITMAP hbmpPencil, hbmpCrayon, hbmpMarker, hbmpPen, hbmpFork;
HBITMAP hbmpPicture, hbmpOld;

void AddItem(HWND hwnd, PTSTR pstr, HBITMAP hbmp)
{
    int lbItem;

    lbItem = SendMessage(hwnd, LB_ADDSTRING, 0, (LPARAM)pstr);
    SendMessage(hwnd, LB_SETITEMDATA, (WPARAM)lbItem, (LPARAM)hbmp);
}


void AddComboItem(HWND hwnd, PTSTR pstr, HBITMAP hbmp)
{
    int lbItem;
    lbItem = SendMessage(hwnd, CB_ADDSTRING, 0, (LPARAM)pstr);
    SendMessage(hwnd, CB_SETITEMDATA, (WPARAM)lbItem, (LPARAM)hbmp);
}





INT_PTR CALLBACK DlgDrawProc(HWND hDlg, UINT message,
        UINT wParam, LONG lParam)
{
    HWND hListBox;
    PMEASUREITEMSTRUCT pmis;
    PDRAWITEMSTRUCT pdis;
    HDC hdcMem;
       HBITMAP hbmp;
    TCHAR achBuffer[BUFFER];
    size_t cch;
    int yPos;
    int lbItem;
    TEXTMETRIC tm;
    RECT rcBitmap;
    HRESULT hr;

    switch (message)
    {
         case WM_INITDIALOG:

            // Load the bitmaps. g_hInst is the global HINSTANCE handle.
            hbmpPencil = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_PENCIL));
            hbmpCrayon = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_CRAYON));
            hbmpMarker = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_MARKER));
            hbmpPen = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_PEN));
            hbmpFork = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_FORK));

            // Retrieve the list box handle.
            //hListBox = GetDlgItem(hDlg, IDC_LIST_STUFF);

            // Initialize the list box text and associate a bitmap
            // with each list box item.
           /*
            AddItem(hListBox, L"pencil", hbmpPencil);
            AddItem(hListBox, L"crayon", hbmpCrayon);
            AddItem(hListBox, L"marker", hbmpMarker);
            AddItem(hListBox, L"pen",    hbmpPen);
            AddItem(hListBox, L"fork",   hbmpFork);
            SetFocus(hListBox);
            SendMessage(hListBox, LB_SETCURSEL, 0, 0);
*/

            HWND hCombo;
            hCombo = GetDlgItem(hDlg, IDC_COMBO1);
            AddComboItem(hCombo, L"pencil", hbmpPencil);
            AddComboItem(hCombo, L"crayon", hbmpCrayon);
            AddComboItem(hCombo, L"marker", hbmpMarker);
            AddComboItem(hCombo, L"pen",    hbmpPen);
            AddComboItem(hCombo, L"fork",   hbmpFork);

            return TRUE;

        case WM_MEASUREITEM:

            pmis = (PMEASUREITEMSTRUCT) lParam;

            // Set the height of the list box items.
            pmis->itemHeight = YBITMAP;

            return TRUE;

        case WM_DRAWITEM:

            pdis = (PDRAWITEMSTRUCT) lParam;

            // If there are no list box items, skip this message.
            if (pdis->itemID == -1)
            {
                break;
            }

            // Draw the bitmap and text for the list box item. Draw a
            // rectangle around the bitmap if it is selected.
            switch (pdis->itemAction)
            {
                case ODA_SELECT:
                case ODA_DRAWENTIRE:

                    // Draw the bitmap associated with the item.
                    //
                    // Get the item bitmap.
                    hbmpPicture = (HBITMAP)SendMessage(pdis->hwndItem,
                        CB_GETITEMDATA, pdis->itemID, 0);

                    // Create a compatible device context.
                    hdcMem = CreateCompatibleDC(pdis->hDC);

                    // Select the item bitmap into the compatible device
                    // context and save the old bitmap.
                    hbmpOld = (HBITMAP) SelectObject(hdcMem, hbmpPicture);

                    // Copy the bitmap into the compatible device context.
                    BitBlt(pdis->hDC,
                        pdis->rcItem.left, pdis->rcItem.top,
                        pdis->rcItem.right - pdis->rcItem.left,
                        pdis->rcItem.bottom - pdis->rcItem.top,
                        hdcMem, 0, 0, SRCCOPY);

                    // Draw the string associated with the item.
                    //
                    // Get the item string from the list box.
                    SendMessage(pdis->hwndItem, CB_GETLBTEXT,
                        pdis->itemID, (LPARAM)achBuffer);

                    // Get the metrics for the current font.
                    GetTextMetrics(pdis->hDC, &tm);

                    // Calculate the vertical position for the item string
                    // so that the string will be vertically centered in the
                    // item rectangle.
                    yPos = (pdis->rcItem.bottom + pdis->rcItem.top -
                        tm.tmHeight) / 2;

                    // Get the character length of the item string.
//                    hr = StringCchLength(achBuffer, BUFFER, &cch);
                    //if (FAILED(hr))
                    {
                        cch = wcslen(achBuffer);
                        // TODO: Handle error.
                    }

                    // Draw the string in the item rectangle, leaving a six
                    // pixel gap between the item bitmap and the string.
                    TextOut(pdis->hDC, XBITMAP + 6, yPos, achBuffer, cch);

                    // Clean up.
                    SelectObject(hdcMem, hbmpOld);
                    DeleteDC(hdcMem);

                    // Is the item selected?
                    if (pdis->itemState & ODS_SELECTED)
                    {
                        // Set RECT coordinates to surround only the
                        // bitmap.
                        rcBitmap.left = pdis->rcItem.left;
                        rcBitmap.top = pdis->rcItem.top;
                        rcBitmap.right = pdis->rcItem.left + XBITMAP;
                        rcBitmap.bottom = pdis->rcItem.top + YBITMAP;

                        // Draw a rectangle around bitmap to indicate
                        // the selection.
                        //DrawFocusRect(pdis->hDC, &rcBitmap);
                        DrawFocusRect(pdis->hDC, &rcBitmap);
                    }
                    break;

                case ODA_FOCUS:

                    // Do not process focus changes. The focus caret
                    // (outline rectangle) indicates the selection.
                    // The IDOK button indicates the final
                    // selection.
                    break;
            }
            return TRUE;

        case WM_COMMAND:

            switch (LOWORD(wParam))
            {
                case IDC_BTN_TEST:
                    // Get the selected item's text.
                    lbItem = SendMessage(GetDlgItem(hDlg, IDC_COMBO1),
                        CB_GETCURSEL, 0, 0);

                    // Get the selected item's bitmap.
                    hbmp = (HBITMAP) SendMessage(GetDlgItem(hDlg, IDC_COMBO1),
                         CB_GETITEMDATA, lbItem, 0);


                    // trivial test to see that we can compare the ITEMDATA of an item
                    // to some arbitrary  thing. In this case, I'm checking to see if the image is
                    // a particular one.
                    if (hbmp != hbmpFork)
                    {
                        MessageBox(hDlg, L"Try again!", L"Oops", MB_OK);
                        return FALSE;
                    }
                    else
                    {
                        MessageBox(hDlg, L"You're right!", L"Congratulations.", MB_OK);

                      // Fall through.
                    }

                case IDCANCEL:

                    // Destroy the dialog box.

                    EndDialog(hDlg, TRUE);
                    return TRUE;

                default:

                    return FALSE;
            }

        case WM_DESTROY:

            // Free the bitmap resources.
            DeleteObject(hbmpPencil);
            DeleteObject(hbmpCrayon);
            DeleteObject(hbmpMarker);
            DeleteObject(hbmpPen);
            DeleteObject(hbmpFork);

            return TRUE;

        default:
            return FALSE;

    }
    return FALSE;
}



int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    hInst = hInstance;
    InitCommonControls();

    // The user interface is a modal dialog box
    return DialogBox(hInstance, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgDrawProc);
}







resource.rc




resource.rc

// Generated by ResEdit 1.5.11
// Copyright (C) 2006-2012
// http://www.resedit.net

#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "resource.h"




//
// Bitmap resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDB_CRAYON         BITMAP         "bitmap2.bmp"


LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDB_FORK           BITMAP         "bitmap5.bmp"


LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDB_MARKER         BITMAP         "bitmap3.bmp"


LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDB_PEN            BITMAP         "bitmap4.bmp"


LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDB_PENCIL         BITMAP         "bitmap1.bmp"



//
// Dialog resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
DLG_MAIN DIALOGEX 6, 5, 194, 84
STYLE DS_3DLOOK | DS_CENTER | DS_SETFONT | WS_CAPTION | WS_VISIBLE | WS_GROUP | WS_THICKFRAME | WS_SYSMENU
CAPTION "Code::Blocks Template Dialog App"
FONT 8, "Tahoma", 0, 0, 1
{
    PUSHBUTTON      "&Test", IDC_BTN_TEST, 67, 62, 46, 15
    PUSHBUTTON      "&Quit", IDC_BTN_QUIT, 141, 62, 46, 15
    COMBOBOX        IDC_COMBO1, 7, 7, 180, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS | CBS_OWNERDRAWFIXED
}



//
// Manifest resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
1                  RT_MANIFEST    ".\\manifest.xml"







resource.h




resource.h

#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif

#define DLG_MAIN                                101
#define IDB_PENCIL                              103
#define IDB_CRAYON                              105
#define IDB_MARKER                              107
#define IDB_PEN                                 109
#define IDB_FORK                                111
#define IDC_COMBO1                              1000
#define IDC_BTN_TEST                            1001
#define IDC_BTN_QUIT                            1002





manifest.xml



manifest.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
    </dependentAssembly>
  </dependency>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel

          level="asInvoker"

          uiAccess="false"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>


你好FOLKS,



终于解决了问题!!这很有趣。正如enhzflep说我尝试使用清单。它确实得到了aero的外观(边框和按钮),但是我没有得到我想要的东西,它是一个所有者绘制的组合框,它的外观和行为就像一个组合框下拉列表。所以我必须做的是:



1)从系统32加载UXTHEME DLL

注意:这仅适用于WinXP及更高版本。

2)获取你需要的模块的功能。

3)在WM_PAINT消息下绘制下拉列表样式外观的背景。请参阅零件和状态(msdn)

4)从 - WM_MOUSEMOVE,ODA_FOCUS(来自WM_DRAWITEM)和ODA_SELECT(选择后)调用InvalidateRect

结束时出现一些闪烁问题。您需要监视状态并尽可能少地调用InvalidateRect。



如果需要更详细的代码片段答案,请告诉我。

再次感谢很多人!!!
Hi FOLKS,

Finally got the problem solved!! It was quite interesting. As enhzflep said I tried using the manifest. It does get the aero look (border and buttons) but I did not get what I wanted which is a owner drawn combo box which looks and behaves as a combo box drop down list. So what I had to do was:

1) Load the UXTHEME DLL from system 32
Note: This works only with WinXP and later.
2) Get func ptr s for the modules you will need.
3) Under WM_PAINT message paint the background for the look of drop list style. Please refer to Parts and states(msdn)
4) Call InvalidateRect from - WM_MOUSEMOVE, ODA_FOCUS(from WM_DRAWITEM) and ODA_SELECT(after selection)
Ended with some flickering problems. You will need to monitor the states and call InvalidateRect as minimally as possible.

In case if a more detailed answer with code snippets is needed please let me know.
And again thanks a lot guys!!!


当然。一旦你拥有一些东西,风格就在你身上。基本上,所有者绘制的东西很容易造成风格的不一致。 In such cases, you many want to think to making the whole application to look according your own styles and ignoring the system style setting. This is a matter of graphical industrial design and design decisions.



\"But there is no guarantee that it may work with later version of window\"? I don’t think this is a real factor. Eventually, Windows itself should die, I would like to see that. The descendant system is supposed to inherit .NET legacy, but not Win32 legacy, which is already pretty ill. Before it happens, new versions of Windows based on Win32 will most likely guarantee the compatibility of WM_PAINT functionality. Note that owner drawing is not really coupled with WM_PAINT.



—SA
Of course. As soon as you owner-draw something, the style is on you. Basically, owner-drawing of something can easily create inconsistencies in style. In such cases, you many want to think to making the whole application to look according your own styles and ignoring the system style setting. This is a matter of graphical industrial design and design decisions.

"But there is no guarantee that it may work with later version of window"? I don't think this is a real factor. Eventually, Windows itself should die, I would like to see that. The descendant system is supposed to inherit .NET legacy, but not Win32 legacy, which is already pretty ill. Before it happens, new versions of Windows based on Win32 will most likely guarantee the compatibility of WM_PAINT functionality. Note that owner drawing is not really coupled with WM_PAINT.

—SA


这篇关于所有者绘制组合下拉列表不保留aero样式。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆