首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在调用DDX_Control之前,如何更改用DDX_Control初始化的控件(CListBox)的样式

在调用DDX_Control之前,如何更改用DDX_Control初始化的控件(CListBox)的样式
EN

Stack Overflow用户
提问于 2019-05-25 15:18:06
回答 2查看 311关注 0票数 1

我正在修改一个已有的项目,并且对话框中的控件在某些情况下会被子类化为不同的主题(在其他情况下,我会完全不去管它)。在DoDataExchange()期间调用DDX_Control()时,ListBox的hwnd已经应用了样式。具体地说,此时即使我执行SetWindowLongPtr()LBS_OWNERDRAWFIXED也不能工作。所谓“不工作”,我的意思是,尽管应用了样式,但CListBox不会接收所有者描述消息。

相反,如果我避免使用DDX_Control(),而只是执行一个create操作,那么ListBox确实会接收到消息,并且可以被拥有者绘制。但是如果我这样做,现在有两个HWND,其中只有一个是由GetDlgItem()返回的。我相信如果需要的话,我可以做到这一点,但我想知道是否有秘密来拦截对话框中控件(实际上是一个CPropertyPage)的HWND创建。

下面是不起作用的代码,如果可能的话,还有更多“起作用”但不是我想要的方式的注释代码。

代码语言:javascript
复制
void CMyPropertySheet::DoDataExchange(CDataExchange* pDX)
{
    HWND hWndCtrl;
    pDX->m_pDlgWnd->GetDlgItem(IDC_LIST1, &hWndCtrl);

    if (themed) {
        DWORD style = GetWindowLongPtr(hWndCtrl, GWL_STYLE) | LBS_OWNERDRAWFIXED;
        SetWindowLongPtr(hWndCtrl, GWL_STYLE, style);
        DDX_Control(pDX, IDC_LIST1, m_listbox);
        //RECT wr;
        //::GetWindowRect(hWndCtrl, &wr);
        //m_listbox.Create(style, wr, this, IDC_LIST1);
    } else {
        DDX_Control(pDX, IDC_LIST1, m_listbox);
    }

我可能应该补充说,我尝试过对窗口进行子类化,但没有帮助,而且CMyPropertySheet::PreSubclassWindow也不够快。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-05-27 14:32:14

一些创建标志,如LBS_OWNERDRAWFIXEDLBS_SORT被缓存,之后修改它们没有任何效果。您必须更改模板,或者只是复制列表框。复制旧列表框的样式,然后隐藏该列表框,更改其ID,并在旧列表框的基础上创建一个新列表框。然后,您必须删除DDX_Control(pDX, IDC_LIST1, m_listbox)

下面的示例从设置了排序标志的标准列表开始。它复制列表框并禁用排序选项。

为简单起见,此示例避免使用LBS_OWNERDRAWFIXED,而是使用LBS_SORT

代码语言:javascript
复制
class CMyPropertyPage : public CPropertyPage
{
public:
    CListBox m_listbox;
    int m_listbox_index;

    CMyPropertyPage(int idd) : CPropertyPage(idd)
    {
        m_listbox_index = 1;
    }   

    void DoDataExchange(CDataExchange* pDX)
    {
        //This function is automatically called before 
        //CPropertyPage::OnInitDialog is complete
        //On the first call, IDC_LIST1 will point to the template listbox
        if(m_listbox.m_hWnd)
        {
            //m_listbox is ready, 
            //IDC_LIST1 will refer to the new listbox
            DDX_LBIndex(pDX, IDC_LIST1, m_listbox_index);
        }
    }

    BOOL OnInitDialog()
    {
        CPropertyPage::OnInitDialog();

        CListBox* old_listbox = (CListBox*)GetDlgItem(IDC_LIST1);
        if(old_listbox)
        {
            DWORD style = ~LBS_SORT & GetWindowLongPtr(old_listbox->m_hWnd, GWL_STYLE);
            CRect rc;
            old_listbox->GetWindowRect(&rc);
            ScreenToClient(&rc);
            old_listbox->SetDlgCtrlID(0);//change the old ID to something unused
            old_listbox->ShowWindow(SW_HIDE); //hide the old listbox
            m_listbox.Create(style | WS_BORDER, rc, this, IDC_LIST1);
            m_listbox.SetFont(GetFont());
        }

        ASSERT(m_listbox.GetDlgCtrlID() == IDC_LIST1);
        m_listbox.AddString(L"2");
        m_listbox.AddString(L"1");
        m_listbox.AddString(L"0");

        UpdateData(FALSE);

        return TRUE;
    }
};

class CMyWinApp : public CWinApp
{
    BOOL InitInstance()
    {
        CWinApp::InitInstance();
        CPropertySheet sh;
        CMyPropertyPage page(IDD_PAGE1);
        sh.AddPage(&page);
        sh.DoModal();
        return TRUE;
    }
} myapp;
票数 1
EN

Stack Overflow用户

发布于 2019-05-27 03:21:03

好吧,我不确定我是否推荐给任何人,但我最终找到了修改模板的方法。我不得不使用VirtualProtect来解锁模板的内存。

代码语言:javascript
复制
for (int i = 0; i < m_pages.GetSize(); i++) {
    CPropertyPage* pPage = GetPage(i);
    PROPSHEETPAGE* tpsp = &pPage->m_psp;

    const DLGTEMPLATE* pTemplate;
    if (tpsp->dwFlags & PSP_DLGINDIRECT) {
        pTemplate = tpsp->pResource;
    } else {
        HRSRC hResource = ::FindResource(tpsp->hInstance, tpsp->pszTemplate, RT_DIALOG);
        if (hResource == NULL) return false;
        HGLOBAL hTemplate = LoadResource(tpsp->hInstance, hResource);
        if (hTemplate == NULL) return false;
        pTemplate = (LPCDLGTEMPLATE)LockResource(hTemplate);
        if (pTemplate == NULL) return false;
    }

    if (afxOccManager != NULL) {
        DLGITEMTEMPLATE *pItem = _AfxFindFirstDlgItem(pTemplate);
        DLGITEMTEMPLATE *pNextItem;
        BOOL bDialogEx = IsDialogEx(pTemplate);

        int iItem, iItems = DlgTemplateItemCount(pTemplate);

        for (iItem = 0; iItem < iItems; iItem++) {
            pNextItem = _AfxFindNextDlgItem(pItem, bDialogEx);
            DWORD dwOldProtect, tp;
            if (bDialogEx) {
                _DialogSplitHelper::DLGITEMTEMPLATEEX *pItemEx = (_DialogSplitHelper::DLGITEMTEMPLATEEX *)pItem;
                if (pItemEx->id == IDC_LIST1) {
                    if (VirtualProtect(&pItemEx->style, sizeof(pItemEx->style), PAGE_READWRITE, &dwOldProtect)) {
                        pItemEx->style |= LBS_OWNERDRAWFIXED;
                        VirtualProtect(&pItemEx->style, sizeof(pItemEx->style), dwOldProtect, &tp);
                    }
                }
            } else {
                if (pItem->id == IDC_LIST1) {
                    if (VirtualProtect(&pItem->style, sizeof(pItem->style), PAGE_READWRITE, &dwOldProtect)) {
                        pItem->style |= LBS_OWNERDRAWFIXED;
                        VirtualProtect(&pItem->style, sizeof(pItem->style), dwOldProtect, &tp);
                    }
                }
            }
            pItem = pNextItem;
        }
    }
}
return true;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56302660

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档