static LRESULT CALLBACK EditProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { EditCtrl *w = (EditCtrl *)dwRefData; CrashIf(w->hwnd != (HWND)lp); if (w->preFilter) { bool discard = false; auto res = w->preFilter(hwnd, msg, wp, lp, discard); if (discard) { return res; } } if (WM_NCDESTROY == msg) { RemoveWindowSubclass(GetParent(w->hwnd), EditParentProc, 0); RemoveWindowSubclass(w->hwnd, EditProc, 0); return DefSubclassProc(hwnd, msg, wp, lp); } // Node: this is sent during creation, which is too early for us (we didn't // subclass the window yet) // currently, we force it with SetWindowPos(... SMP_FRAMECHANGED) if (WM_NCCALCSIZE == msg) { NCCALCSIZE_PARAMS *p = (NCCALCSIZE_PARAMS *)lp; RECT orig = p->rgrc[0]; LRESULT res = DefSubclassProc(hwnd, msg, wp, lp); RECT curr = p->rgrc[0]; w->ncDx = RectDx(orig) - RectDx(curr); w->ncDy = RectDy(orig) - RectDy(curr); return res; } return DefSubclassProc(hwnd, msg, wp, lp); }
//----------------------------------------------------------------------------- // main application //----------------------------------------------------------------------------- void CVsVGuiWindow::Detach() { if ( m_hTimerCallbackId != 0 ) { MTimerMessage::removeCallback( m_hTimerCallbackId ); m_hTimerCallbackId = 0; } if ( m_hMainPanel.Get() ) { m_hMainPanel->MarkForDeletion(); m_hMainPanel = NULL; } if ( m_hVGuiContext != vgui::DEFAULT_VGUI_CONTEXT ) { vgui::ivgui()->DestroyContext( m_hVGuiContext ); m_hVGuiContext = vgui::DEFAULT_VGUI_CONTEXT; } // detach if ( m_hWnd ) { // kill the timer if any g_pMaterialSystem->RemoveView( m_hWnd ); RemoveWindowSubclass( m_hWnd, SubclassCallback, s_subclassId ); m_hWnd = NULL; } if ( m_hKeyFocusWnd ) { RemoveWindowSubclass( m_hKeyFocusWnd, KeyFocusSubclassCallback, s_subclassId ); m_hKeyFocusWnd = NULL; } }
RichEdit::~RichEdit() { #ifndef MY_RICHEDIT_NO_OLE if (_pRichEditOle) _pRichEditOle->Release(); #endif RemoveWindowSubclass(GetParent(getHwnd()), RichEdit::ParentWndProc, 0); RemoveWindowSubclass(getHwnd(), RichEdit::WndProc, 0); if (getHwnd()) DestroyWindow(getHwnd()); }
CBookmarksToolbar::~CBookmarksToolbar() { ImageList_Destroy(m_himl); RevokeDragDrop(m_hToolbar); m_pbtdh->Release(); RemoveWindowSubclass(m_hToolbar,BookmarksToolbarProcStub,SUBCLASS_ID); RemoveWindowSubclass(GetParent(m_hToolbar),BookmarksToolbarParentProcStub,PARENT_SUBCLASS_ID); CBookmarkItemNotifier::GetInstance().RemoveObserver(this); }
// the real list view intercepts these keys to control editing static LRESULT CALLBACK editSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIDSubclass, DWORD_PTR dwRefData) { uiTable *t = (uiTable *) dwRefData; HRESULT hr; switch (uMsg) { case WM_KEYDOWN: switch (wParam) { // TODO handle VK_TAB and VK_SHIFT+VK_TAB case VK_RETURN: hr = uiprivTableFinishEditingText(t); if (hr != S_OK) { // TODO } return 0; // yes, the real list view just returns here case VK_ESCAPE: hr = uiprivTableAbortEditingText(t); if (hr != S_OK) { // TODO } return 0; } break; // the real list view also forces these flags case WM_GETDLGCODE: return DLGC_HASSETSEL | DLGC_WANTALLKEYS; case WM_NCDESTROY: if (RemoveWindowSubclass(hwnd, editSubProc, uIDSubclass) == FALSE) logLastError(L"RemoveWindowSubclass()"); // fall through } return DefSubclassProc(hwnd, uMsg, wParam, lParam); }
static LRESULT CALLBACK groupSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { uiGroup *g = uiGroup(dwRefData); WINDOWPOS *wp = (WINDOWPOS *) lParam; MINMAXINFO *mmi = (MINMAXINFO *) lParam; int minwid, minht; LRESULT lResult; if (handleParentMessages(hwnd, uMsg, wParam, lParam, &lResult) != FALSE) return lResult; switch (uMsg) { case WM_WINDOWPOSCHANGED: if ((wp->flags & SWP_NOSIZE) != 0) break; groupRelayout(g); return 0; case WM_GETMINMAXINFO: lResult = DefWindowProcW(hwnd, uMsg, wParam, lParam); uiWindowsControlMinimumSize(uiWindowsControl(g), &minwid, &minht); mmi->ptMinTrackSize.x = minwid; mmi->ptMinTrackSize.y = minht; return lResult; case WM_NCDESTROY: if (RemoveWindowSubclass(hwnd, groupSubProc, uIdSubclass) == FALSE) logLastError(L"error removing groupbox subclass"); break; } return DefSubclassProc(hwnd, uMsg, wParam, lParam); }
void DeleteFrameRateWnd(FrameRateWnd *w) { if (w) { RemoveWindowSubclass(w->hwndAssociatedWith, WndProcFrameRateAssociated, 0); free(w); } }
LRESULT CALLBACK TextBoxSubclassProc( _In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam, _In_ UINT_PTR uIdSubclass, _In_ ULONG_PTR dwRefData ) { switch (uMsg) { case WM_NCDESTROY: RemoveWindowSubclass(hWnd, TextBoxSubclassProc, uIdSubclass); break; case WM_GETDLGCODE: { if (wParam == VK_RETURN) return DLGC_WANTALLKEYS; } break; case WM_CHAR: { if (wParam == VK_RETURN) { SendMessage(GetParent(hWnd), WM_COMMAND, IDC_TEXT_RETURN, 0); return 0; } } break; } return DefSubclassProc(hWnd, uMsg, wParam, lParam); }
static LRESULT CALLBACK opacitySliderSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { ID2D1RenderTarget *rt; struct colorDialog *c; D2D1_POINT_2F *pos; D2D1_SIZE_F *size; c = (struct colorDialog *) dwRefData; switch (uMsg) { case msgD2DScratchPaint: rt = (ID2D1RenderTarget *) lParam; drawOpacitySlider(c, rt); return 0; case msgD2DScratchLButtonDown: pos = (D2D1_POINT_2F *) wParam; size = (D2D1_SIZE_F *) lParam; c->a = 1 - (pos->x / size->width); updateDialog(c, NULL); return 0; case WM_NCDESTROY: if (RemoveWindowSubclass(hwnd, opacitySliderSubProc, uIdSubclass) == FALSE) logLastError(L"error removing color dialog opacity slider subclass"); break; } return DefSubclassProc(hwnd, uMsg, wParam, lParam); }
LRESULT CALLBACK Explorerplusplus::MainWndTaskbarThumbnailProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { if(uMsg == m_uTaskbarButtonCreatedMessage) { if(m_pTaskbarList != NULL) { m_pTaskbarList->Release(); } CoCreateInstance(CLSID_TaskbarList,NULL,CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pTaskbarList)); m_pTaskbarList->HrInit(); m_bTaskbarInitialised = TRUE; /* Add each of the jump list tasks. */ SetupJumplistTasks(); /* Register each of the tabs. */ for(auto itr = m_TabProxyList.begin();itr != m_TabProxyList.end();itr++) { BOOL bActive = (itr->iTabId == m_iObjectIndex); RegisterTab(itr->hProxy,EMPTY_STRING,bActive); HandleTabText(itr->iTabId); SetTabIcon(itr->iTabId); } RemoveWindowSubclass(hwnd,MainWndProcStub,0); return 0; } return DefSubclassProc(hwnd,uMsg,wParam,lParam); }
LRESULT CALLBACK DropWindowSubclass(HWND hwnd,UINT uMsg, WPARAM wParam,LPARAM lParam,UINT_PTR uIdSubclass,DWORD_PTR dwRefData) { switch(uMsg) { case WM_APP_COPYOPERATIONFINISHED: { PastedFilesInfo_t *ppfi = reinterpret_cast<PastedFilesInfo_t *>(wParam); ppfi->pao->EndOperation(ppfi->hrCopy,NULL,ppfi->dwEffect); ppfi->pDropHandler->Release(); free((void *)ppfi); RemoveWindowSubclass(hwnd,DropWindowSubclass,SUBCLASS_ID); return 0; } break; /* TODO: The window we're subclassing may be destroyed while the subclass is active. This should be handled in some way. */ /*case WM_NCDESTROY: RemoveWindowSubclass(hwnd,DropWindowSubclass,SUBCLASS_ID); break;*/ } return DefSubclassProc(hwnd,uMsg,wParam,lParam); }
void subclass_uninstall(HWND hwnd) { DWORD_PTR state = 0; if(!GetWindowSubclass(hwnd, fproc, 0, &state) || !state) return; _log_("subclass_uninstall: thread = %d, hwnd = %08X", GetCurrentThreadId(), hwnd); if(RemoveWindowSubclass(hwnd, fproc, 0)) free((void*)state); }
/*-------------------------------------------------- restore window procedure of "BaseBar" ----------------------------------------------------*/ void UnSubclassBaseBar(void) { if(m_hwndBaseBar && IsWindow(m_hwndBaseBar) && m_bBaseBarSubclassed) { RemoveWindowSubclass(m_hwndBaseBar, SubclassProcBaseBar, 0); } m_bBaseBarSubclassed = FALSE; }
static void Unsubclass(TreeCtrl* w) { if (!w) { return; } if (w->hwndSubclassId != 0) { BOOL ok = RemoveWindowSubclass(w->hwnd, TreeProc, SUBCLASS_ID); CrashIf(false && !ok); w->hwndSubclassId = 0; } if (w->hwndParentSubclassId != 0) { BOOL ok = RemoveWindowSubclass(w->parent, TreeParentProc, SUBCLASS_ID); CrashIf(false && !ok); w->hwndParentSubclassId = 0; } }
/*-------------------------------------------------- restore window procedure of "Desktop User Pane" ----------------------------------------------------*/ void UnSubclassUserPaneXP(void) { if(m_hwndUserPaneXP && IsWindow(m_hwndUserPaneXP) && m_bUserPaneXPSubclassed) { RemoveWindowSubclass(m_hwndUserPaneXP, SubclassProcUserPaneXP, 0); SendMessage(GetParent(m_hwndUserPaneXP), WM_SYSCOLORCHANGE, 0, 0); } m_bUserPaneXPSubclassed = FALSE; }
AeroControlBase::~AeroControlBase() { for (std::map<HWND, UINT_PTR>::const_iterator it = subclassedControls.begin(); it != subclassedControls.end(); ++it) { RemoveWindowSubclass(it->first, SubclassProc, it->second); } BufferedPaintUnInit(); if (gdiplusToken) GdiplusShutdown(gdiplusToken); }
LRESULT AeroControlBase::ProgressbarWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_ENABLE: case WM_STYLECHANGED: { LRESULT res = DefSubclassProc(hWnd, uMsg, wParam, lParam); InvalidateRgn(hWnd, NULL, FALSE); return res; } break; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); RECT rc; GetWindowRect(hWnd, &rc); MapWindowPoints(NULL, hWnd, (LPPOINT)&rc, 2); if (hdc) { PaintControl(hWnd, hdc, &ps.rcPaint, false); BP_PAINTPARAMS params = { sizeof(BP_PAINTPARAMS) }; params.dwFlags = 0L; HDC hdcPaint = NULL; HPAINTBUFFER hBufferedPaint = BeginBufferedPaint(hdc, &rc, BPBF_TOPDOWNDIB, ¶ms, &hdcPaint); if (hdcPaint) { COLORREF cr = RGB(0x00, 0x00, 0x00); SetPixel(hdcPaint, 0, 0, cr); SetPixel(hdcPaint, 0, RECTHEIGHT(rc) - 1, cr); SetPixel(hdcPaint, RECTWIDTH(rc) - 1, 0, cr); SetPixel(hdcPaint, RECTWIDTH(rc) - 1, RECTHEIGHT(rc) - 1, cr); EndBufferedPaint(hBufferedPaint, TRUE); } } EndPaint(hWnd, &ps); return 0; } break; case WM_NCDESTROY: case WM_DESTROY: RemoveWindowSubclass(hWnd, SubclassProc, Static); subclassedControls.erase(hWnd); break; } return DefSubclassProc(hWnd, uMsg, wParam, lParam); }
CWindowsWin32Window::~CWindowsWin32Window() { if(--s_winCount == 0) { s_pumpTask = nullptr; //The windows don't need it anymore. //the pump task will not be deleted until it's dequeued from the thread task list. } //A comment on SetWindowSubclass says to remove the subclass before destroying the window. RemoveWindowSubclass(_win,WindowProc,0); DestroyWindow(_win); }
// SingleRegWatcher INT_PTR CALLBACK SingleRegWatcher::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ switch(uMsg){ case WM_INITDIALOG: { // Create subclass of edit box function SetWindowSubclass(GetDlgItem(hWnd, IDC_REGVALUE), &EditSubclassProc, m_editSubclassID, NULL); } break; case WM_CLOSE: { RemoveWindowSubclass(GetDlgItem(hWnd, IDC_REGVALUE), &EditSubclassProc, m_editSubclassID); break; } case WM_ENABLE: EnableWindow(GetDlgItem(hWnd, IDC_REGVALUE), (BOOL)wParam); break; case H86_UPDATE_SYS_DATA: { Mutex sysMutex((void*)wParam); sys_state_ptr sysState=(sys_state_ptr)lParam; sysMutex.Lock(); nsEmulator::Emulator* e=nsEmulator::Emulator::GetInstance(); uint16 val=e->ReadReg(m_regNum); wchar_t data[5]; _itow((uint32)val, data, 16); SetDlgItemText(hWnd, IDC_REGVALUE, data); sysMutex.Unlock(); } break; case H86_USER_INPUT: { sys_state_ptr sysState=(sys_state_ptr)lParam; nsEmulator::Emulator* e=nsEmulator::Emulator::GetInstance(); wchar_t data[5]; GetDlgItemText(hWnd, IDC_REGVALUE, data, 5); uint16 val=wcstol(data, NULL, 16); e->WriteReg(m_regNum, val); } break; default: return 0; } return 0; }
/** * Subclass procedure for any dialog control. Reports key press events to * ooDialog for those key presses connected to an ooDialog method by the user. * * All messages are passed on unchanged to the control. * * processKeyPress() is used to actually decipher the key press data and set * up the ooDialog method invocation. That function documents what is sent on * to the ooDialog method. */ LRESULT CALLBACK KeyPressSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR id, DWORD_PTR dwData) { SUBCLASSDATA *pSubclassData = (SUBCLASSDATA *)dwData; if ( ! pSubclassData ) { return DefSubclassProc(hwnd, msg, wParam, lParam); } KEYPRESSDATA *pKeyData = (KEYPRESSDATA *)pSubclassData->pData; switch ( msg ) { case WM_GETDLGCODE: /* Don't do anything for now. This message has some interesting * uses, perhaps a future enhancement. */ break; case WM_SYSKEYDOWN: /* Sent when the alt key is down. We need both WM_SYSKEYDOWN and * WM_KEYDOWN to catch everything that a keyboard hook catches. */ if ( pKeyData->key[wParam] && !(lParam & KEY_RELEASED) && !(lParam & KEY_WASDOWN) ) { processKeyPress(pSubclassData, wParam, lParam); } break; case WM_KEYDOWN: /* WM_KEYDOWN will never have KEY_RELEASED set. */ if ( pKeyData->key[wParam] && !(lParam & KEY_WASDOWN) ) { processKeyPress(pSubclassData, wParam, lParam); } break; case WM_NCDESTROY: /* The window is being destroyed, remove the subclass, clean up * memory. */ RemoveWindowSubclass(hwnd, KeyPressSubclassProc, id); freeKeyPressData(pSubclassData); break; } return DefSubclassProc(hwnd, msg, wParam, lParam); }
LRESULT CALLBACK CDialog::MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { LRESULT result = DefSubclassProc(hWnd, uMsg, wParam, lParam); switch (uMsg) { case WM_PAINT: { // Draw arrow on top of the button RECT buttonRect; GetClientRect(hWnd, &buttonRect); int arrowX = buttonRect.right - 18; int arrowY = buttonRect.top + 4; RECT arrowRect = { arrowX, arrowY, arrowX + 14, arrowY + 14 }; HDC dc = GetDC(hWnd); const WORD DFCS_MENUARROWDOWN = 0x0010; // Undocumented DWORD drawFlags = DFCS_TRANSPARENT | DFCS_MENUARROWDOWN | (IsWindowEnabled(hWnd) ? 0 : DFCS_INACTIVE); DrawFrameControl(dc, &arrowRect, DFC_MENU, drawFlags); ReleaseDC(hWnd, dc); } break; case WM_GETTEXT: { // Append 3 spaces to the button text to move text to the left so // that it looks better with BS_CENTER. WCHAR* str = (WCHAR*)lParam + result; str[0] = str[1] = str[2] = L' '; str[3] = '\0'; result += 3; } break; case WM_GETTEXTLENGTH: result += 3; break; case WM_NCDESTROY: RemoveWindowSubclass(hWnd, MenuButtonProc, uIdSubclass); break; } return result; }
static LRESULT CALLBACK fontDialogSampleSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { ID2D1RenderTarget *rt; struct fontDialog *f; switch (uMsg) { case msgD2DScratchPaint: rt = (ID2D1RenderTarget *) lParam; f = (struct fontDialog *) dwRefData; fontDialogDrawSampleText(f, rt); return 0; case WM_NCDESTROY: if (RemoveWindowSubclass(hwnd, fontDialogSampleSubProc, uIdSubclass) == FALSE) logLastError(L"error removing font dialog sample text subclass"); break; } return DefSubclassProc(hwnd, uMsg, wParam, lParam); }
static LRESULT CALLBACK previewSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { ID2D1RenderTarget *rt; struct colorDialog *c; c = (struct colorDialog *) dwRefData; switch (uMsg) { case msgD2DScratchPaint: rt = (ID2D1RenderTarget *) lParam; drawPreview(c, rt); return 0; case WM_NCDESTROY: if (RemoveWindowSubclass(hwnd, previewSubProc, uIdSubclass) == FALSE) logLastError(L"error removing color dialog previewer subclass"); break; } return DefSubclassProc(hwnd, uMsg, wParam, lParam); }
/*-------------------------------------------------- clear up ----------------------------------------------------*/ void EndTrayNotify(void) { if(m_hwndTrayNotify && IsWindow(m_hwndTrayNotify)) { SetWindowLong(m_hwndTrayNotify, GWL_STYLE, m_oldStyle); RemoveWindowSubclass(m_hwndTrayNotify, SubclassProcTrayNotify, 0); SetClassLong(m_hwndTrayNotify, GCL_STYLE, m_oldClassStyle); InvalidateRect(m_hwndTrayNotify, NULL, TRUE); if(m_hwndToolbar) { SendMessage(m_hwndToolbar, WM_SYSCOLORCHANGE, 0, 0); InvalidateRect(m_hwndToolbar, NULL, TRUE); } } m_hwndTrayNotify = NULL; m_hwndToolbar = NULL; }
LRESULT CALLBACK TaskDialogSubclassProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam, _In_ UINT_PTR uIdSubclass, _In_ ULONG_PTR dwRefData ) { PPH_SETUP_CONTEXT context = (PPH_SETUP_CONTEXT)dwRefData; switch (uMsg) { case WM_TASKDIALOGINIT: { if (IsMinimized(hwndDlg)) ShowWindow(hwndDlg, SW_RESTORE); else ShowWindow(hwndDlg, SW_SHOW); SetForegroundWindow(hwndDlg); } break; case WM_NCDESTROY: { RemoveWindowSubclass(hwndDlg, TaskDialogSubclassProc, uIdSubclass); } break; case WM_APP + IDD_ERROR: { SetupShowUpdatingErrorDialog(context); } break; } return DefSubclassProc(hwndDlg, uMsg, wParam, lParam); }
// Sets the new buddy // LRESULT NEAR PASCAL setbuddy(PUDSTATE np, HWND hwndBuddy) { HWND hOldBuddy; TCHAR szClName[10]; hOldBuddy = np->hwndBuddy; if ((np->hwndBuddy = hwndBuddy) == NULL) { pickbuddy(np); hwndBuddy = np->hwndBuddy; } if (hOldBuddy && (hOldBuddy != hwndBuddy)) RemoveWindowSubclass(hOldBuddy, ArrowKeyProc, 0); np->uClass = CLASS_UNKNOWN; if (hwndBuddy) { if (np->ci.style & UDS_ARROWKEYS) SetWindowSubclass(hwndBuddy, ArrowKeyProc, 0, (DWORD)np); GetClassName(hwndBuddy, szClName, ARRAYSIZE(szClName)); if (!lstrcmpi(szClName, c_szEdit)) { np->uClass = CLASS_EDIT; } else if (!lstrcmpi(szClName, c_szListbox)) { np->uClass = CLASS_LISTBOX; } } anchor(np); return MAKELRESULT(hOldBuddy, 0); }
LRESULT CALLBACK Explorerplusplus::TabSubclassProc(HWND hTab,UINT msg,WPARAM wParam,LPARAM lParam) { switch(msg) { case WM_INITMENU: OnInitTabMenu(wParam); SendMessage(m_hContainer,WM_INITMENU,wParam,lParam); break; case WM_MENUSELECT: /* Forward the message to the main window so it can handle menu help. */ SendMessage(m_hContainer,WM_MENUSELECT,wParam,lParam); break; case WM_MEASUREITEM: SendMessage(m_hContainer,WM_MEASUREITEM,wParam,lParam); break; case WM_DRAWITEM: SendMessage(m_hContainer,WM_DRAWITEM,wParam,lParam); break; case WM_LBUTTONDOWN: OnTabCtrlLButtonDown(wParam,lParam); break; case WM_LBUTTONUP: OnTabCtrlLButtonUp(); break; case WM_MOUSEMOVE: OnTabCtrlMouseMove(wParam,lParam); break; case WM_MBUTTONUP: SendMessage(m_hContainer,WM_APP_TABMCLICK,wParam,lParam); break; case WM_RBUTTONUP: OnTabCtrlRButtonUp(wParam,lParam); break; case WM_CAPTURECHANGED: { if((HWND)lParam != hTab) ReleaseCapture(); m_bTabBeenDragged = FALSE; } break; case WM_LBUTTONDBLCLK: { TCHITTESTINFO info; int ItemNum; DWORD dwPos; POINT MousePos; dwPos = GetMessagePos(); MousePos.x = GET_X_LPARAM(dwPos); MousePos.y = GET_Y_LPARAM(dwPos); ScreenToClient(hTab,&MousePos); /* The cursor position will be tested to see if there is a tab beneath it. */ info.pt.x = LOWORD(lParam); info.pt.y = HIWORD(lParam); ItemNum = TabCtrl_HitTest(m_hTabCtrl,&info); if(info.flags != TCHT_NOWHERE && m_bDoubleClickTabClose) { CloseTab(ItemNum); } } break; case WM_NCDESTROY: RemoveWindowSubclass(m_hTabCtrl,TabSubclassProcStub,0); break; } return DefSubclassProc(hTab,msg,wParam,lParam); }
LRESULT CALLBACK ArrowKeyProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT uIdSubclass, DWORD dwRefData) { PUDSTATE np = (PUDSTATE)dwRefData; int cDetants; switch (uMsg) { case WM_NCDESTROY: RemoveWindowSubclass(hWnd, ArrowKeyProc, 0); np->hwndBuddy = NULL; if (np->fUpDownDestroyed) { // The buddy was destroyed after updown so free the memory now // And pass off to the message to who we subclassed... LocalFree((HLOCAL)np); } break; case WM_GETDLGCODE: return (DefSubclassProc(hWnd, uMsg, wParam, lParam) | DLGC_WANTARROWS); case WM_KEYDOWN: switch (wParam) { case VK_UP: case VK_DOWN: if (GetCapture() != np->ci.hwnd) { /* Get the value from the buddy if this is the first key down */ if (!(lParam&(1L<<30))) { getint(np); } /* Update the visuals and bump the value */ np->bDown = (wParam == VK_DOWN); squish(np, !np->bDown, np->bDown); bump(np); } return(0L); default: break; } break; case WM_KEYUP: switch (wParam) { case VK_UP: case VK_DOWN: if (GetCapture() != np->ci.hwnd) { squish(np, FALSE, FALSE); } return(0L); default: break; } break; // this is dumb. // wm_char's aren't sent for arrow commands.. // what you're really eating here is & and (. #if 0 case WM_CHAR: switch (wParam) { case VK_UP: case VK_DOWN: return(0L); default: break; } break; #endif case WM_KILLFOCUS: // Reset wheel scroll amount gcWheelDelta = 0; break; case WM_SETFOCUS: Assert(gcWheelDelta == 0); break; default: if (uMsg == g_msgMSWheel && GetCapture() != np->ci.hwnd) { #if defined(WINNT) && defined(WM_MOUSEWHEEL) int iWheelDelta = (int)(short)HIWORD(wParam); #else int iWheelDelta = (int)wParam; #endif // Update count of scroll amount gcWheelDelta -= iWheelDelta; cDetants = gcWheelDelta / WHEEL_DELTA; if (cDetants != 0) { gcWheelDelta %= WHEEL_DELTA; #if defined(WINNT) && defined(WM_MOUSEWHEEL) if (wParam & (MK_SHIFT | MK_CONTROL)) { break; } #else if (GetKeyState(VK_SHIFT) < 0 || GetKeyState(VK_CONTROL) < 0) { break; } #endif getint(np); np->bDown = (cDetants > 0); cDetants = abs(cDetants); while (cDetants-- > 0) { squish(np, !np->bDown, np->bDown); bump(np); } squish(np, FALSE, FALSE); } return 1; } break; } return DefSubclassProc(hWnd, uMsg, wParam, lParam); }
LRESULT AeroControlBase::ButtonWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_SETTEXT: case WM_ENABLE: case WM_STYLECHANGED: { LRESULT res = DefSubclassProc(hWnd, uMsg, wParam, lParam); InvalidateRgn(hWnd, NULL, FALSE); return res; } break; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); if(hdc) { LONG_PTR dwStyle = GetWindowLongPtr(hWnd, GWL_STYLE); LONG_PTR dwButtonStyle = LOWORD(dwStyle); LONG_PTR dwButtonType = dwButtonStyle&0xF; RECT rcClient; VERIFY(GetClientRect(hWnd, &rcClient)); if((dwButtonType&BS_GROUPBOX)==BS_GROUPBOX) { /// /// it must be a group box /// HTHEME hTheme = OpenThemeData(hWnd, L"Button"); if(hTheme) { BP_PAINTPARAMS params = { sizeof(BP_PAINTPARAMS) }; params.dwFlags = BPPF_ERASE; RECT rcExclusion = rcClient; params.prcExclude = &rcExclusion; /// /// We have to calculate the exclusion rect and therefore /// calculate the font height. We select the control's font /// into the DC and fake a drawing operation: /// HFONT hFontOld = (HFONT)SendMessage(hWnd, WM_GETFONT, 0L, NULL); if(hFontOld) hFontOld = (HFONT) SelectObject(hdc, hFontOld); RECT rcDraw = rcClient; DWORD dwFlags = DT_SINGLELINE; /// /// we use uppercase A to determine the height of text, so we /// can draw the upper line of the groupbox: /// DrawTextW(hdc, L"A", -1, &rcDraw, dwFlags|DT_CALCRECT); if (hFontOld) { SelectObject(hdc, hFontOld); hFontOld = NULL; } VERIFY(InflateRect(&rcExclusion, -1, -1*RECTHEIGHT(rcDraw))); HDC hdcPaint = NULL; HPAINTBUFFER hBufferedPaint = BeginBufferedPaint(hdc, &rcClient, BPBF_TOPDOWNDIB, ¶ms, &hdcPaint); if (hdcPaint) { /// /// now we again retrieve the font, but this time we select it into /// the buffered DC: /// hFontOld = (HFONT)SendMessage(hWnd, WM_GETFONT, 0L, NULL); if(hFontOld) hFontOld = (HFONT) SelectObject(hdcPaint, hFontOld); VERIFY(PatBlt(hdcPaint, 0, 0, RECTWIDTH(rcClient), RECTHEIGHT(rcClient), BLACKNESS)); VERIFY(S_OK==BufferedPaintSetAlpha(hBufferedPaint, &ps.rcPaint, 0x00)); int iPartId = BP_GROUPBOX; int iState = GetStateFromBtnState(dwStyle, FALSE, FALSE, 0L, iPartId, FALSE); DTTOPTS DttOpts = {sizeof(DTTOPTS)}; DttOpts.dwFlags = DTT_COMPOSITED | DTT_GLOWSIZE; DttOpts.crText = RGB(255, 255, 255); DttOpts.iGlowSize = 12; // Default value VERIFY(DetermineGlowSize(&DttOpts.iGlowSize)); COLORREF cr = RGB(0x00, 0x00, 0x00); VERIFY(GetEditBorderColor(hWnd, &cr)); /// /// add the alpha value: /// cr |= 0xff000000; std::unique_ptr<Pen> myPen( new Pen(Color(cr), 1) ); std::unique_ptr<Graphics> myGraphics( new Graphics(hdcPaint) ); int iY = RECTHEIGHT(rcDraw)/2; Rect rr = Rect(rcClient.left, rcClient.top+iY, RECTWIDTH(rcClient), RECTHEIGHT(rcClient)-iY-1); GraphicsPath path; GetRoundRectPath(&path, rr, 10); myGraphics->DrawPath(myPen.get(), &path); //myGraphics->DrawRectangle(myPen, rcClient.left, rcClient.top + iY, // RECTWIDTH(rcClient)-1, RECTHEIGHT(rcClient) - iY-1); myGraphics.reset(); myPen.reset(); int iLen = GetWindowTextLength(hWnd); if(iLen) { iLen+=5; // 1 for terminating zero, 4 for DT_MODIFYSTRING LPWSTR szText = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*iLen); if(szText) { iLen = GetWindowTextW(hWnd, szText, iLen); if(iLen) { int iX = RECTWIDTH(rcDraw); rcDraw = rcClient; rcDraw.left += iX; DrawTextW(hdcPaint, szText, -1, &rcDraw, dwFlags|DT_CALCRECT); VERIFY(PatBlt(hdcPaint, rcDraw.left, rcDraw.top , RECTWIDTH(rcDraw) + 3, RECTHEIGHT(rcDraw), BLACKNESS)); rcDraw.left++; rcDraw.right++; VERIFY(S_OK==DrawThemeTextEx(hTheme, hdcPaint, iPartId, iState, szText, -1, dwFlags, &rcDraw, &DttOpts)); } VERIFY(!LocalFree(szText)); } } if (hFontOld) { SelectObject(hdcPaint, hFontOld); hFontOld = NULL; } VERIFY(S_OK==EndBufferedPaint(hBufferedPaint, TRUE)); } VERIFY(S_OK==CloseThemeData(hTheme)); } } else if(dwButtonType==BS_CHECKBOX || dwButtonType==BS_AUTOCHECKBOX || dwButtonType==BS_3STATE || dwButtonType==BS_AUTO3STATE || dwButtonType==BS_RADIOBUTTON || dwButtonType==BS_AUTORADIOBUTTON) { HTHEME hTheme = OpenThemeData(hWnd, L"Button"); if(hTheme) { HDC hdcPaint = NULL; BP_PAINTPARAMS params = { sizeof(BP_PAINTPARAMS) }; params.dwFlags = BPPF_ERASE; HPAINTBUFFER hBufferedPaint = BeginBufferedPaint(hdc, &rcClient, BPBF_TOPDOWNDIB, ¶ms, &hdcPaint); if (hdcPaint) { VERIFY(PatBlt(hdcPaint, 0, 0, RECTWIDTH(rcClient), RECTHEIGHT(rcClient), BLACKNESS)); VERIFY(S_OK==BufferedPaintSetAlpha(hBufferedPaint, &ps.rcPaint, 0x00)); LRESULT dwCheckState = SendMessage(hWnd, BM_GETCHECK, 0, NULL); POINT pt; RECT rc; GetWindowRect(hWnd, &rc); GetCursorPos(&pt); BOOL bHot = PtInRect(&rc, pt); BOOL bFocus = GetFocus()==hWnd; int iPartId = BP_CHECKBOX; if(dwButtonType==BS_RADIOBUTTON || dwButtonType==BS_AUTORADIOBUTTON) iPartId = BP_RADIOBUTTON; int iState = GetStateFromBtnState(dwStyle, bHot, bFocus, dwCheckState, iPartId, FALSE); int bmWidth = int(ceil(13.0 * GetDeviceCaps(hdcPaint, LOGPIXELSX) / 96.0)); UINT uiHalfWidth = (RECTWIDTH(rcClient) - bmWidth)/2; /// /// we have to use the whole client area, otherwise we get only partially /// drawn areas: /// RECT rcPaint = rcClient; if(dwButtonStyle & BS_LEFTTEXT) { rcPaint.left += uiHalfWidth; rcPaint.right += uiHalfWidth; } else { rcPaint.left -= uiHalfWidth; rcPaint.right -= uiHalfWidth; } /// /// we assume that bmWidth is both the horizontal and the vertical /// dimension of the control bitmap and that it is square. bm.bmHeight /// seems to be the height of a striped bitmap because it is an absurdly /// high dimension value /// if((dwButtonStyle&BS_VCENTER)==BS_VCENTER) /// BS_VCENTER is BS_TOP|BS_BOTTOM { int h = RECTHEIGHT(rcPaint); rcPaint.top = (h - bmWidth) / 2; rcPaint.bottom = rcPaint.top + bmWidth; } else if(dwButtonStyle&BS_TOP) { rcPaint.bottom = rcPaint.top + bmWidth; } else if(dwButtonStyle&BS_BOTTOM) { rcPaint.top = rcPaint.bottom - bmWidth; } else // default: center the checkbox/radiobutton vertically { int h = RECTHEIGHT(rcPaint); rcPaint.top = (h - bmWidth) / 2; rcPaint.bottom = rcPaint.top + bmWidth; } VERIFY(S_OK==DrawThemeBackground(hTheme, hdcPaint, iPartId, iState, &rcPaint, NULL)); rcPaint = rcClient; VERIFY(S_OK==GetThemeBackgroundContentRect(hTheme, hdcPaint, iPartId, iState, &rcPaint, &rc)); if(dwButtonStyle & BS_LEFTTEXT) rc.right -= bmWidth + 2 * GetSystemMetrics(SM_CXEDGE); else rc.left += bmWidth + 2 * GetSystemMetrics(SM_CXEDGE); DTTOPTS DttOpts = {sizeof(DTTOPTS)}; DttOpts.dwFlags = DTT_COMPOSITED | DTT_GLOWSIZE; DttOpts.crText = RGB(255, 255, 255); DttOpts.iGlowSize = 12; // Default value VERIFY(DetermineGlowSize(&DttOpts.iGlowSize)); HFONT hFontOld = (HFONT)SendMessage(hWnd, WM_GETFONT, 0L, NULL); if(hFontOld) hFontOld = (HFONT) SelectObject(hdcPaint, hFontOld); int iLen = GetWindowTextLength(hWnd); if(iLen) { iLen+=5; // 1 for terminating zero, 4 for DT_MODIFYSTRING LPWSTR szText = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*iLen); if(szText) { iLen = GetWindowTextW(hWnd, szText, iLen); if(iLen) { DWORD dwFlags = DT_SINGLELINE /*|DT_VCENTER*/; if(dwButtonStyle&BS_MULTILINE) { dwFlags|=DT_WORDBREAK; dwFlags&= ~(DT_SINGLELINE |DT_VCENTER); } if((dwButtonStyle&BS_CENTER)==BS_CENTER) /// BS_CENTER is BS_LEFT|BS_RIGHT dwFlags|=DT_CENTER; else if(dwButtonStyle&BS_LEFT) dwFlags|=DT_LEFT; else if(dwButtonStyle&BS_RIGHT) dwFlags|=DT_RIGHT; if((dwButtonStyle&BS_VCENTER)==BS_VCENTER) /// BS_VCENTER is BS_TOP|BS_BOTTOM dwFlags|=DT_VCENTER; else if(dwButtonStyle&BS_TOP) dwFlags|=DT_TOP; else if(dwButtonStyle&BS_BOTTOM) dwFlags|=DT_BOTTOM; else dwFlags|=DT_VCENTER; VERIFY(S_OK==DrawThemeTextEx(hTheme, hdcPaint, iPartId, iState, szText, -1, dwFlags, &rc, &DttOpts)); /// /// if our control has the focus, we also have to draw the focus rectangle: /// if(bFocus) { /// /// now calculate the text size: /// RECT rcDraw = rc; /// /// we use GDI's good old DrawText, because it returns much more /// accurate data than DrawThemeTextEx, which takes the glow /// into account which we don't want: /// VERIFY(DrawTextW(hdcPaint, szText, -1, &rcDraw, dwFlags|DT_CALCRECT)); if(dwFlags&DT_SINGLELINE) { dwFlags &= ~DT_VCENTER; RECT rcDrawTop; DrawTextW(hdcPaint, szText, -1, &rcDrawTop, dwFlags|DT_CALCRECT); rcDraw.top = rcDraw.bottom - RECTHEIGHT(rcDrawTop); } if(dwFlags & DT_RIGHT) { int iWidth = RECTWIDTH(rcDraw); rcDraw.right = rc.right; rcDraw.left = rcDraw.right - iWidth; } RECT rcFocus; VERIFY(IntersectRect(&rcFocus, &rc, &rcDraw)); DrawFocusRect(&rcFocus, hdcPaint); } } VERIFY(!LocalFree(szText)); } } if (hFontOld) { SelectObject(hdcPaint, hFontOld); hFontOld = NULL; } VERIFY(S_OK==EndBufferedPaint(hBufferedPaint, TRUE)); } VERIFY(S_OK==CloseThemeData(hTheme)); } } else if(BS_PUSHBUTTON==dwButtonType || BS_DEFPUSHBUTTON==dwButtonType) { /// /// it is a push button /// HTHEME hTheme = OpenThemeData(hWnd, L"Button"); if(hTheme) { HDC hdcPaint = NULL; BP_PAINTPARAMS params = { sizeof(BP_PAINTPARAMS) }; params.dwFlags = BPPF_ERASE; HPAINTBUFFER hBufferedPaint = BeginBufferedPaint(hdc, &rcClient, BPBF_TOPDOWNDIB, ¶ms, &hdcPaint); if (hdcPaint) { VERIFY(PatBlt(hdcPaint, 0, 0, RECTWIDTH(rcClient), RECTHEIGHT(rcClient), BLACKNESS)); VERIFY(S_OK==BufferedPaintSetAlpha(hBufferedPaint, &ps.rcPaint, 0x00)); LRESULT dwCheckState = SendMessage(hWnd, BM_GETCHECK, 0, NULL); POINT pt; RECT rc; GetWindowRect(hWnd, &rc); GetCursorPos(&pt); BOOL bHot = PtInRect(&rc, pt); BOOL bFocus = GetFocus()==hWnd; int iPartId = BP_PUSHBUTTON; if(dwButtonStyle==BS_RADIOBUTTON || dwButtonStyle==BS_AUTORADIOBUTTON) iPartId = BP_RADIOBUTTON; int iState = GetStateFromBtnState(dwStyle, bHot, bFocus, dwCheckState, iPartId, GetCapture()==hWnd); /// /// we have to use the whole client area, otherwise we get only partially /// drawn areas: /// RECT rcPaint = rcClient; VERIFY(S_OK==DrawThemeBackground(hTheme, hdcPaint, iPartId, iState, &rcPaint, NULL)); VERIFY(S_OK==GetThemeBackgroundContentRect(hTheme, hdcPaint, iPartId, iState, &rcPaint, &rc)); DTTOPTS DttOpts = {sizeof(DTTOPTS)}; DttOpts.dwFlags = DTT_COMPOSITED | DTT_GLOWSIZE; DttOpts.crText = RGB(255, 255, 255); DttOpts.iGlowSize = 12; // Default value VERIFY(DetermineGlowSize(&DttOpts.iGlowSize)); HFONT hFontOld = (HFONT)SendMessage(hWnd, WM_GETFONT, 0L, NULL); if(hFontOld) hFontOld = (HFONT) SelectObject(hdcPaint, hFontOld); int iLen = GetWindowTextLength(hWnd); if(iLen) { iLen+=5; // 1 for terminating zero, 4 for DT_MODIFYSTRING LPWSTR szText = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*iLen); if(szText) { iLen = GetWindowTextW(hWnd, szText, iLen); if(iLen) { DWORD dwFlags = DT_SINGLELINE | DT_CENTER | DT_VCENTER; VERIFY(S_OK==DrawThemeTextEx(hTheme, hdcPaint, iPartId, iState, szText, -1, dwFlags, &rc, &DttOpts)); /// /// if our control has the focus, we also have to draw the focus rectangle: /// if(bFocus) { RECT rcDraw = rcClient; VERIFY(InflateRect(&rcDraw, -3, -3)); DrawFocusRect(&rcDraw, hdcPaint); } } VERIFY(!LocalFree(szText)); } } if (hFontOld) { SelectObject(hdcPaint, hFontOld); hFontOld = NULL; } VERIFY(S_OK==EndBufferedPaint(hBufferedPaint, TRUE)); } VERIFY(S_OK==CloseThemeData(hTheme)); } } else //PaintControl(hWnd, hdc, &ps.rcPaint, (m_dwFlags & WD_DRAW_BORDER)!=0); PaintControl(hWnd, hdc, &ps.rcPaint, false); } EndPaint(hWnd, &ps); return 0; } break; case WM_DESTROY: case WM_NCDESTROY: RemoveWindowSubclass(hWnd, SubclassProc, Button); subclassedControls.erase(hWnd); break; } return DefSubclassProc(hWnd, uMsg, wParam, lParam); }
LRESULT AeroControlBase::StaticWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_SETTEXT: case WM_ENABLE: case WM_STYLECHANGED: { LRESULT res = DefSubclassProc(hWnd, uMsg, wParam, lParam); InvalidateRgn(hWnd, NULL, FALSE); return res; } break; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); if(hdc) { HDC hdcPaint = NULL; RECT rcClient; VERIFY(GetClientRect(hWnd, &rcClient)); LONG_PTR dwStyle = GetWindowLongPtr(hWnd, GWL_STYLE); LONG_PTR dwStyleEx = GetWindowLongPtr(hWnd, GWL_EXSTYLE); HTHEME hTheme = OpenThemeData(NULL, L"ControlPanelStyle"); if(hTheme) { HPAINTBUFFER hBufferedPaint = NULL; if (dwStyleEx & WS_EX_TRANSPARENT) { BP_PAINTPARAMS paintParams = {0}; paintParams.cbSize = sizeof(paintParams); paintParams.dwFlags = BPPF_ERASE; BLENDFUNCTION blendf = {0}; blendf.BlendOp = AC_SRC_OVER; blendf.AlphaFormat = AC_SRC_ALPHA; blendf.SourceConstantAlpha = 255; paintParams.pBlendFunction = &blendf; hBufferedPaint = BeginBufferedPaint(hdc, &rcClient, BPBF_TOPDOWNDIB, &paintParams, &hdcPaint); } else hBufferedPaint = BeginBufferedPaint(hdc, &rcClient, BPBF_TOPDOWNDIB, NULL, &hdcPaint); if (hdcPaint) { VERIFY(PatBlt(hdcPaint, 0, 0, RECTWIDTH(rcClient), RECTHEIGHT(rcClient), BLACKNESS)); VERIFY(S_OK==BufferedPaintSetAlpha(hBufferedPaint, &ps.rcPaint, 0x00)); LONG_PTR dwStaticStyle = dwStyle&0x1F; if(dwStaticStyle==SS_ICON || dwStaticStyle==SS_BITMAP) { bool bIcon = dwStaticStyle==SS_ICON; HANDLE hBmpIco = (HANDLE)SendMessage(hWnd, STM_GETIMAGE, bIcon ? IMAGE_ICON:IMAGE_BITMAP, NULL); if(hBmpIco) { std::unique_ptr<Bitmap> pBmp( bIcon ? new Bitmap((HICON)hBmpIco) : new Bitmap((HBITMAP)hBmpIco, NULL) ); std::unique_ptr<Graphics> myGraphics( new Graphics(hdcPaint) ); std::unique_ptr<CachedBitmap> pcbmp( new CachedBitmap(pBmp.get(), myGraphics.get()) ); VERIFY(Ok==myGraphics->DrawCachedBitmap(pcbmp.get(), 0,0)); } } else if(SS_BLACKRECT==dwStaticStyle || SS_GRAYRECT==dwStaticStyle || SS_WHITERECT==dwStaticStyle) { ARGB argb = 0L; switch (dwStaticStyle) { case SS_BLACKRECT: argb = 0xFF000000; break; case SS_GRAYRECT: argb = 0xFF808080; break; case SS_WHITERECT: argb = 0xFFFFFFFF; break; default: ASSERT(0); break; } Color clr(argb); FillRect(&rcClient, hdcPaint, clr); } else if(SS_BLACKFRAME==dwStaticStyle || SS_GRAYFRAME==dwStaticStyle || SS_WHITEFRAME==dwStaticStyle) { ARGB argb = 0L; switch (dwStaticStyle) { case SS_BLACKFRAME: argb = 0xFF000000; break; case SS_GRAYFRAME: argb = 0xFF808080; break; case SS_WHITEFRAME: argb = 0xFFFFFFFF; break; } Color clr(argb); DrawRect(&rcClient, hdcPaint, DashStyleSolid, clr, 1.0); } else { DTTOPTS DttOpts = {sizeof(DTTOPTS)}; DttOpts.dwFlags = DTT_COMPOSITED | DTT_GLOWSIZE; DttOpts.crText = RGB(255, 255, 255); DttOpts.iGlowSize = 12; // Default value VERIFY(DetermineGlowSize(&DttOpts.iGlowSize)); HFONT hFontOld = (HFONT)SendMessage(hWnd, WM_GETFONT, 0L, NULL); if(hFontOld) hFontOld = (HFONT) SelectObject(hdcPaint, hFontOld); int iLen = GetWindowTextLength(hWnd); if(iLen) { iLen+=5; // 1 for terminating zero, 4 for DT_MODIFYSTRING LPWSTR szText = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*iLen); if(szText) { iLen = GetWindowTextW(hWnd, szText, iLen); if(iLen) { DWORD dwFlags = DT_WORDBREAK; switch (dwStaticStyle) { case SS_CENTER: dwFlags |= DT_CENTER; break; case SS_RIGHT: dwFlags |= DT_RIGHT; break; case SS_LEFTNOWORDWRAP: dwFlags &= ~DT_WORDBREAK; break; } if(dwStyle & SS_CENTERIMAGE) { dwFlags |= DT_VCENTER; dwFlags &= ~DT_WORDBREAK; } if(dwStyle & SS_ENDELLIPSIS) dwFlags |= DT_END_ELLIPSIS|DT_MODIFYSTRING; else if(dwStyle & SS_PATHELLIPSIS) dwFlags |= DT_PATH_ELLIPSIS|DT_MODIFYSTRING; else if(dwStyle & SS_WORDELLIPSIS) dwFlags |= DT_WORD_ELLIPSIS|DT_MODIFYSTRING; if (dwStyleEx&WS_EX_RIGHT) dwFlags |= DT_RIGHT; if(dwStyle & SS_NOPREFIX) dwFlags |= DT_NOPREFIX; VERIFY(S_OK==DrawThemeTextEx(hTheme, hdcPaint, 0, 0, szText, -1, dwFlags, &rcClient, &DttOpts)); if(dwStyle&SS_SUNKEN || dwStyle&WS_BORDER) DrawRect(&rcClient, hdcPaint, DashStyleSolid, Color(0xFF, 0,0,0), 1.0); } VERIFY(!LocalFree(szText)); } } if (hFontOld) { SelectObject(hdcPaint, hFontOld); hFontOld = NULL; } } VERIFY(S_OK==EndBufferedPaint(hBufferedPaint, TRUE)); } VERIFY(S_OK==CloseThemeData(hTheme)); } } EndPaint(hWnd, &ps); return 0; } break; case WM_NCDESTROY: case WM_DESTROY: RemoveWindowSubclass(hWnd, SubclassProc, Static); subclassedControls.erase(hWnd); break; } return DefSubclassProc(hWnd, uMsg, wParam, lParam); }