I have a strange one. I have two forms of my x64 app, one is a DeskBand and one uses a normal Window. Both have their own class names that are registered (the normal Window version adds Exe
to the class name). Several owner-draw buttons are created on the main Window. They have text, icon, and tooltip. Everything works fine if I run as the DeskBand or the Window version (on Win10), but if I have both the Deskband active (checked to show up on the TaskBar) and Window version running, when I close the Window (.exe) version, explorer.exe
crashes on each ::DestroyWindow()
called for each button (if full speed you get one crash, but if you step through it in debug mode, each one causes a crash). It's done on the WM_DESTROY
message being sent to the app. I checked spy, each button has its own handle, the window class for the main windows are correct (different between deskband and window). The DeskBand version is still running fine afterwards.
The event viewer information is:
Faulting application name: explorer.exe, version: 10.0.18362.628, time stamp: 0xc3041aa6
Faulting module name: comctl32.dll, version: 6.10.18362.657, time stamp: 0xabe19732
Exception code: 0xc0000005
Fault offset: 0x000000000006fd23
Faulting process id: 0x4658
Faulting application start time: 0x01d5f510f0740d42
Faulting application path: C:\WINDOWS\explorer.exe
Faulting module path: C:\WINDOWS\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.18362.657_none_e6c5b579130e3898\comctl32.dll
Report Id: 37ac6912-eb7c-43c8-b566-821b53569f15
Faulting package full name:
Faulting package-relative application ID:
Here's the basic part that creates and destroys the buttons.
HWND CMyOwnerDrawButton::Create(int x, int y, int nwidth, int nheight, HWND hwndparent, HINSTANCE hresinstance, bool tintover, bool themed)
{
// if duplicate just return existing handle
if (m_hWnd) {
return m_hWnd;
}
// set initial flags state
SetThemed(themed);
SetTintOver(tintover);
// get text for button and tooltip
CString buttontext;
buttontext.LoadString(hresinstance, m_ResIDText);
m_hWnd=::CreateWindowEx(0,
WC_BUTTON,
buttontext,
BS_OWNERDRAW | BS_ICON | BS_NOTIFY | WS_VISIBLE | WS_CHILD | WS_TABSTOP,
x,
y,
nwidth,
nheight,
hwndparent,
(HMENU) (INT_PTR) m_ID,
NULL,
NULL);
if (m_hWnd) {
// get width of icon to use
int cx=0;
int cy=0;
// get the icon directory
const GRPICONDIR *icondir;
if ((icondir=::GetIconDirectory(hresinstance, m_ResIDIcon))!=NULL) {
// search for the size we want - largest that is smaller than the button
for (UINT i=0;i<icondir->idCount;i++) {
// find x
if (icondir->idEntries[i].bWidth>cx && icondir->idEntries[i].bWidth<nwidth) {
cx=icondir->idEntries[i].bWidth;
// find y
if (icondir->idEntries[i].bHeight>cy && icondir->idEntries[i].bHeight<nheight) {
cy=icondir->idEntries[i].bHeight;
}
}
}
}
// load icon to use - presume all icons are the same size
m_hIcon=(HICON) ::LoadImage(hresinstance, MAKEINTRESOURCE(m_ResIDIcon), IMAGE_ICON, cx, cy, LR_SHARED);
if (m_ResIDIconOver) {
m_hIconOver=(HICON) ::LoadImage(hresinstance, MAKEINTRESOURCE(m_ResIDIconOver), IMAGE_ICON, cx, cy, LR_SHARED);
}
// get icon size actually loaded
if (!::GetIconSizeInfo(m_hIcon, &m_IconSizeInfo)) {
// assume size
m_IconSizeInfo.nBitsPerPixel=1;
m_IconSizeInfo.nHeight=nheight;
m_IconSizeInfo.nWidth=nwidth;
}
// subclass control
::SetWindowSubclass(m_hWnd, SubclassProc, m_ID, (DWORD_PTR) this);
// create tool tip
::CreateToolTip(m_ID, hwndparent, buttontext);
}
return m_hWnd;
}
//-------------------------------------------------------------------------
// Purpose: Destroy button created
//
// Input: na
//
// Output: na
//
// Notes:
//
void CMyOwnerDrawButton::Destroy()
{
if (m_hWnd) {
::ShowWindow(m_hWnd, SW_HIDE);
::DestroyWindow(m_hWnd); // <<<< THIS IS WHERE EXPLORER.EXE CRASHES IF DESKBAND IS ACTIVE
m_hWnd=NULL;
}
}
User contributions licensed under CC BY-SA 3.0