I'm modifying an existing project and a dialog has controls I am subclassing to theme differently in some cases (in other cases I will leave it entirely alone). By the time DDX_Control()
is called during DoDataExchange()
, the hwnd for the ListBox
already has styles applied. Specifically, at this time even if I do SetWindowLongPtr()
, the LBS_OWNERDRAWFIXED
does not work. By "does not work," I mean that although the style is applied, owner draw messages are not received by the CListBox.
Conversely, if I avoid the DDX_Control()
and simply do a create, the ListBox does receive the messages and can be ownerdrawn. But if I do this there are now two HWND, only one of which is returned by GetDlgItem()
. I believe I can make this work if necessary, but I wondered if there is a secret to intercept the HWND creation of the controls in the dialog (actually a CPropertyPage).
Below is code that doesn't work, with more commented code that "works" but isn't the way I wanted it to work, if possible.
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);
}
I should probably add I tried subclassing the window, but it didn't help, and CMyPropertySheet::PreSubclassWindow
wasn't soon enough, either.
OK, I'm not sure I recommend this to anyone, but I did find a way to modify the template, finally. I had to use VirtualProtect to unlock the memory of the template.
Some creation flags like
LBS_OWNERDRAWFIXED
andLBS_SORT
are cached and modifying them afterwards have no effect. You have to change the template, or just make a duplicate of the listbox. Copy the style of the old listbox, then hide that listbox, change its ID, and create a new listbox based on the old one. You then have to removeDDX_Control(pDX, IDC_LIST1, m_listbox)
The example below starts with a standard list which has its sort flag set. It duplicates the listbox and disables the sort option.
For simplicity this example avoids
LBS_OWNERDRAWFIXED
, it usesLBS_SORT
instead.