Something went wrong. Try again.
Reactos
Something went wrong. Try again.
34 kB · 1456 lines
C++
at master
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457/* * Copyright 2003, 2004, 2005 Martin Fuchs * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
// // Explorer clone // // window.cpp // // Martin Fuchs, 23.07.2003 //
#include <precomp.h>
WindowClass::WindowClass(LPCTSTR classname, UINT style_, WNDPROC wndproc){ memset(this, 0, sizeof(WNDCLASSEX));
cbSize = sizeof(WNDCLASSEX); style = style_; hInstance = g_Globals._hInstance; hCursor = LoadCursor(0, IDC_ARROW); this->hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); lpszClassName = classname; lpfnWndProc = wndproc;
_atomClass = 0;}
IconWindowClass::IconWindowClass(LPCTSTR classname, UINT nid, UINT style, WNDPROC wndproc) : WindowClass(classname, style, wndproc){ hIcon = ResIcon(nid); hIconSm = SmallIcon(nid);}
Window::WindowMap Window::s_wnd_map;
Window::CREATORFUNC Window::s_window_creator = NULL;const void* Window::s_new_info = NULL;
HHOOK Window::s_hcbtHook = 0;
Window::StaticWindowData& Window::GetStaticWindowData(){ static StaticWindowData s_initialized_data;
return s_initialized_data;}
Window::Window(HWND hwnd) : WindowHandle(hwnd){ Lock lock(GetStaticWindowData()._map_crit_sect); // protect access to s_wnd_map
s_wnd_map[_hwnd] = this;}
Window::~Window(){ Lock lock(GetStaticWindowData()._map_crit_sect); // protect access to s_wnd_map
s_wnd_map.erase(_hwnd);}
HWND Window::Create(CREATORFUNC creator, DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int w, int h, HWND hwndParent, HMENU hMenu/*, LPVOID lpParam*/){ Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info
s_window_creator = creator; s_new_info = NULL;
return CreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, w, h, hwndParent, hMenu, g_Globals._hInstance, 0/*lpParam*/);}
HWND Window::Create(CREATORFUNC_INFO creator, const void* info, DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int w, int h, HWND hwndParent, HMENU hMenu/*, LPVOID lpParam*/){ Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info
s_window_creator = (CREATORFUNC) creator; s_new_info = info;
return CreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, w, h, hwndParent, hMenu, g_Globals._hInstance, 0/*lpParam*/);}
Window* Window::create_mdi_child(const ChildWndInfo& info, const MDICREATESTRUCT& mcs, CREATORFUNC_INFO creator){ Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info
s_window_creator = (CREATORFUNC) creator; s_new_info = &info;
s_hcbtHook = SetWindowsHookEx(WH_CBT, MDICBTHookProc, 0, GetCurrentThreadId());
HWND hwnd = (HWND) SendMessage(info._hmdiclient, WM_MDICREATE, 0, (LPARAM)&mcs);
// end hook in case it's not already done if (s_hcbtHook) UnhookWindowsHookEx(s_hcbtHook);
Window* child = get_window(hwnd); s_new_info = NULL;
if (child && (!hwnd || !child->_hwnd)) child = NULL;
return child;}
LRESULT CALLBACK Window::MDICBTHookProc(int code, WPARAM wparam, LPARAM lparam){ if (code == HCBT_CREATEWND) { UnhookWindowsHookEx(s_hcbtHook); // use the hook only for the first created window s_hcbtHook = 0;
HWND hwnd = (HWND)wparam;
// create Window controller and associate it with the window handle Window* child = get_window(hwnd);
if (!child) child = create_controller(hwnd); }
return CallNextHookEx(s_hcbtHook, code, wparam, lparam);}
/*Window* Window::create_property_sheet(PropertySheetDialog* ppsd, CREATORFUNC creator, const void* info){ Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info
s_window_creator = creator; s_new_info = info;
s_hcbtHook = SetWindowsHookEx(WH_CBT, PropSheetCBTHookProc, 0, GetCurrentThreadId());
HWND hwnd = (HWND) PropertySheet(ppsd);
UnhookWindowsHookEx(s_hcbtHook);
Window* child = get_window(hwnd); s_new_info = NULL;
if (child && (!hwnd || !child->_hwnd)) child = NULL;
return child;}*/
LRESULT CALLBACK Window::PropSheetCBTHookProc(int code, WPARAM wparam, LPARAM lparam){ if (code == HCBT_CREATEWND) { HWND hwnd = (HWND)wparam;
// create Window controller and associate it with the window handle Window* child = get_window(hwnd);
if (!child) child = create_controller(hwnd); }
return CallNextHookEx(s_hcbtHook, code, wparam, lparam);}
/// get window controller from window handle
Window* Window::get_window(HWND hwnd){ { Lock lock(GetStaticWindowData()._map_crit_sect); // protect access to s_wnd_map
WindowMap::const_iterator found = s_wnd_map.find(hwnd);
if (found!=s_wnd_map.end()) return found->second; }
return NULL;}
/// create controller for a new window
Window* Window::create_controller(HWND hwnd){ if (s_window_creator) { // protect for recursion and create the window object only for the first window Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info
const void* info = s_new_info; s_new_info = NULL;
CREATORFUNC window_creator = s_window_creator; s_window_creator = NULL;
if (info) return CREATORFUNC_INFO(window_creator)(hwnd, info); else return CREATORFUNC(window_creator)(hwnd); }
return NULL;}
LRESULT Window::Init(LPCREATESTRUCT pcs){ return 0;}
LRESULT CALLBACK Window::WindowWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam){ Window* pThis = get_window(hwnd);
if (!pThis) pThis = create_controller(hwnd);
if (pThis) { switch(nmsg) { case WM_COMMAND: return pThis->Command(LOWORD(wparam), HIWORD(wparam));
case WM_NOTIFY: return pThis->Notify(wparam, (NMHDR*)lparam);
case WM_NOTIFYFORMAT: return NFR_CURRENT;
case WM_CREATE: return pThis->Init((LPCREATESTRUCT)lparam);
case WM_NCDESTROY: delete pThis; return 0;
default: return pThis->WndProc(nmsg, wparam, lparam); } } else return DefWindowProc(hwnd, nmsg, wparam, lparam);}
LRESULT Window::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam){ return DefWindowProc(_hwnd, nmsg, wparam, lparam);}
int Window::Command(int id, int code){ return 1; // no command handler found}
int Window::Notify(int id, NMHDR* pnmh){ return 0;}
void Window::CancelModes(){ PostMessage(HWND_BROADCAST, WM_CANCELMODE, 0, 0);}
SubclassedWindow::SubclassedWindow(HWND hwnd) : super(hwnd){ _orgWndProc = SubclassWindow(_hwnd, SubclassedWndProc);
if (!_orgWndProc) delete this;}
LRESULT CALLBACK SubclassedWindow::SubclassedWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam){ SubclassedWindow* pThis = GET_WINDOW(SubclassedWindow, hwnd); assert(pThis);
if (pThis) { switch(nmsg) { case WM_COMMAND: if (!pThis->Command(LOWORD(wparam), HIWORD(wparam))) return 0; break;
case WM_NOTIFY: return pThis->Notify(wparam, (NMHDR*)lparam);
case WM_NOTIFYFORMAT: return NFR_CURRENT;
case WM_CREATE: return pThis->Init((LPCREATESTRUCT)lparam);
case WM_NCDESTROY: delete pThis; return 0;
default: return pThis->WndProc(nmsg, wparam, lparam); } }
return CallWindowProc(pThis->_orgWndProc, hwnd, nmsg, wparam, lparam);}
LRESULT SubclassedWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam){ return CallWindowProc(_orgWndProc, _hwnd, nmsg, wparam, lparam);}
int SubclassedWindow::Command(int id, int code){ return 1; // no command handler found}
int SubclassedWindow::Notify(int id, NMHDR* pnmh){ return CallWindowProc(_orgWndProc, _hwnd, WM_NOTIFY, id, (LPARAM)pnmh);}
ChildWindow::ChildWindow(HWND hwnd, const ChildWndInfo& info) : super(hwnd), _hwndFrame(GetParent(info._hmdiclient)){ _focus_pane = 0; _split_pos = DEFAULT_SPLIT_POS; _last_split = DEFAULT_SPLIT_POS;}
ChildWindow* ChildWindow::create(const ChildWndInfo& info, const RECT& rect, CREATORFUNC_INFO creator, LPCTSTR classname, LPCTSTR title, DWORD style){ MDICREATESTRUCT mcs;
mcs.szClass = classname; mcs.szTitle = title; mcs.hOwner = g_Globals._hInstance; mcs.x = rect.left, mcs.y = rect.top; mcs.cx = rect.right - rect.left; mcs.cy = rect.bottom - rect.top; mcs.style = style; mcs.lParam = 0;
return static_cast<ChildWindow*>(create_mdi_child(info, mcs, creator));}
LRESULT ChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam){ switch(nmsg) { case WM_PAINT: { RECT rc; PaintCanvas canvas(_hwnd); ClientRect rt(_hwnd); rt.left = _split_pos-SPLIT_WIDTH/2; rt.right = _split_pos+SPLIT_WIDTH/2+1; HBRUSH lastBrush = SelectBrush(canvas, GetStockBrush(COLOR_SPLITBAR)); Rectangle(canvas, rt.left, rt.top-1, rt.right, rt.bottom+1); SetRect(&rc, rt.left, rt.top-1, rt.right, rt.bottom+1); DrawEdge(canvas, &rc, EDGE_RAISED, BF_RECT); SelectObject(canvas, lastBrush); break;}
case WM_SETCURSOR: if (LOWORD(lparam) == HTCLIENT) { POINT pt; GetCursorPos(&pt); ScreenToClient(_hwnd, &pt);
if (pt.x>=_split_pos-SPLIT_WIDTH/2 && pt.x<_split_pos+SPLIT_WIDTH/2+1) { SetCursor(LoadCursor(0, IDC_SIZEWE)); return TRUE; } } goto def;
case WM_SIZE: if (wparam != SIZE_MINIMIZED) resize_children(LOWORD(lparam), HIWORD(lparam)); goto def;
case WM_GETMINMAXINFO: DefMDIChildProc(_hwnd, nmsg, wparam, lparam);
{LPMINMAXINFO lpmmi = (LPMINMAXINFO)lparam;
lpmmi->ptMaxTrackSize.x <<= 1; // 2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN lpmmi->ptMaxTrackSize.y <<= 1; // 2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN break;}
case WM_LBUTTONDOWN: { int x = GET_X_LPARAM(lparam);
ClientRect rt(_hwnd);
if (x>=_split_pos-SPLIT_WIDTH/2 && x<_split_pos+SPLIT_WIDTH/2+1) { _last_split = _split_pos; SetCapture(_hwnd); }
break;}
case WM_LBUTTONUP: if (GetCapture() == _hwnd) ReleaseCapture(); break;
case WM_KEYDOWN: if (wparam == VK_ESCAPE) if (GetCapture() == _hwnd) { _split_pos = _last_split; ClientRect rt(_hwnd); resize_children(rt.right, rt.bottom); _last_split = -1; ReleaseCapture(); SetCursor(LoadCursor(0, IDC_ARROW)); } break;
case WM_MOUSEMOVE: if (GetCapture() == _hwnd) { int x = GET_X_LPARAM(lparam);
ClientRect rt(_hwnd);
if (x>=0 && x<rt.right) { _split_pos = x; resize_children(rt.right, rt.bottom); rt.left = x-SPLIT_WIDTH/2; rt.right = x+SPLIT_WIDTH/2+1; InvalidateRect(_hwnd, &rt, FALSE); UpdateWindow(_left_hwnd); UpdateWindow(_hwnd); UpdateWindow(_right_hwnd); } } break;
case PM_DISPATCH_COMMAND: switch(LOWORD(wparam)) { case ID_GO_BACK: if (!_url_history.empty()) { const String& url = jump_to_int(_url_history.top());
if (jump_to_int(url)) set_url(url);
_url_history.pop(); } break;
case ID_GO_FORWARD: //@@ break;
case ID_GO_UP: ///@todo break;
case ID_GO_HOME: //@@ break;
default: return FALSE; } return TRUE;
case WM_MDIACTIVATE: if ((HWND)lparam == _hwnd) { SendMessage(_hwndFrame, PM_SETSTATUSTEXT, 0, (LPARAM)_statusText.c_str()); SendMessage(_hwndFrame, PM_URL_CHANGED, 0, (LPARAM)_url.c_str()); } break;
case PM_JUMP_TO_URL: return go_to((LPCTSTR)lparam)? TRUE: FALSE;
default: def: return DefMDIChildProc(_hwnd, nmsg, wparam, lparam); }
return 0;}
void ChildWindow::resize_children(int cx, int cy){ HDWP hdwp = BeginDeferWindowPos(2); RECT rt;
rt.left = 0; rt.top = 0; rt.right = cx; rt.bottom = cy;
if (_left_hwnd) { cx = _split_pos + SPLIT_WIDTH/2;
hdwp = DeferWindowPos(hdwp, _left_hwnd, 0, rt.left, rt.top, _split_pos-SPLIT_WIDTH/2-rt.left, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE); } else { _split_pos = 0; cx = 0; }
if (_right_hwnd) hdwp = DeferWindowPos(hdwp, _right_hwnd, 0, rt.left+cx+1, rt.top, rt.right-cx, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
EndDeferWindowPos(hdwp);}
bool ChildWindow::go_to(LPCTSTR url){ const String& url_str = jump_to_int(url);
if (!url_str.empty()) { set_url(url_str);
_url_history.push(url_str);
return true; } else return false;}
void ChildWindow::set_url(LPCTSTR url){ if (_url != url) { _url = url;
SendMessage(_hwndFrame, PM_URL_CHANGED, 0, (LPARAM)url); }}
WindowSet Window::s_pretranslate_windows;
void Window::register_pretranslate(HWND hwnd){ s_pretranslate_windows.insert(hwnd);}
void Window::unregister_pretranslate(HWND hwnd){ s_pretranslate_windows.erase(hwnd);}
BOOL Window::pretranslate_msg(LPMSG pmsg){ if ((pmsg->message != WM_KEYDOWN) && (pmsg->message != WM_SYSKEYDOWN) && (pmsg->message != WM_SYSCHAR) && (pmsg->message != WM_CHAR)) { return FALSE; }
for(WindowSet::const_iterator it=Window::s_pretranslate_windows.begin(); it!=s_pretranslate_windows.end(); ++it) if (SendMessage(*it, PM_TRANSLATE_MSG, 0, (LPARAM)pmsg)) return TRUE;
return FALSE;}
WindowSet Window::s_dialogs;
void Window::register_dialog(HWND hwnd){ s_dialogs.insert(hwnd);}
void Window::unregister_dialog(HWND hwnd){ s_dialogs.erase(hwnd);}
BOOL Window::dispatch_dialog_msg(MSG* pmsg){ for(WindowSet::const_iterator it=Window::s_dialogs.begin(); it!=s_dialogs.end(); ++it) if (IsDialogMessage(*it, pmsg)) return TRUE;
return FALSE;}
int Window::MessageLoop(){ MSG msg;
while(GetMessage(&msg, 0, 0, 0)) { try { if (pretranslate_msg(&msg)) continue;
if (dispatch_dialog_msg(&msg)) continue;
TranslateMessage(&msg);
try { DispatchMessage(&msg); } catch(COMException& e) { HandleException(e, 0); } } catch(COMException& e) { HandleException(e, 0); } }
return msg.wParam;}
LRESULT Window::SendParent(UINT nmsg, WPARAM wparam, LPARAM lparam){ HWND parent = GetParent(_hwnd);
if (!parent) return 0;
return SendMessage(parent, nmsg, wparam, lparam);}
LRESULT Window::PostParent(UINT nmsg, WPARAM wparam, LPARAM lparam){ HWND parent = GetParent(_hwnd);
if (!parent) return 0;
return PostMessage(parent, nmsg, wparam, lparam);}
PreTranslateWindow::PreTranslateWindow(HWND hwnd) : super(hwnd){ register_pretranslate(hwnd);}
PreTranslateWindow::~PreTranslateWindow(){ unregister_pretranslate(_hwnd);}
Dialog::Dialog(HWND hwnd) : super(hwnd){ register_dialog(hwnd);}
Dialog::~Dialog(){ unregister_dialog(_hwnd);}
int Dialog::DoModal(UINT nid, CREATORFUNC creator, HWND hwndParent){ Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info
s_window_creator = creator; s_new_info = NULL;
///@todo call Window::pretranslate_msg()
return DialogBoxParam(g_Globals._hInstance, MAKEINTRESOURCE(nid), hwndParent, DialogProc, 0/*lpParam*/);}
int Dialog::DoModal(UINT nid, CREATORFUNC_INFO creator, const void* info, HWND hwndParent){ Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info
s_window_creator = (CREATORFUNC) creator; s_new_info = NULL;
///@todo call Window::pretranslate_msg()
return DialogBoxParam(g_Globals._hInstance, MAKEINTRESOURCE(nid), hwndParent, DialogProc, 0/*lpParam*/);}
INT_PTR CALLBACK Window::DialogProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam){ Window* pThis = get_window(hwnd);
if (pThis) { switch(nmsg) { case WM_COMMAND: pThis->Command(LOWORD(wparam), HIWORD(wparam)); return TRUE; // message has been processed
case WM_NOTIFY: pThis->Notify(wparam, (NMHDR*)lparam); return TRUE; // message has been processed
case WM_NOTIFYFORMAT: SetWindowLongPtr(hwnd, DWLP_MSGRESULT, NFR_CURRENT); // set return value NFR_CURRENT return TRUE; // message has been processed
case WM_NCDESTROY: delete pThis; return TRUE; // message has been processed
default: return pThis->WndProc(nmsg, wparam, lparam); } } else if (nmsg == WM_INITDIALOG) { pThis = create_controller(hwnd);
if (pThis) return pThis->Init(NULL); }
return FALSE; // message has not been processed}
LRESULT Dialog::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam){ return FALSE; // message has not been processed}
int Dialog::Command(int id, int code){ if (code == BN_CLICKED) { EndDialog(_hwnd, id); return 0; // message has been processed }
return 1;}
ResizeManager::ResizeManager(HWND hwnd) : _hwnd(hwnd){ ClientRect clnt(hwnd); _last_size.cx = clnt.right; _last_size.cy = clnt.bottom;
WindowRect rect(hwnd); _min_wnd_size.cx = rect.right - rect.left; _min_wnd_size.cy = rect.bottom - rect.top;}
void ResizeManager::HandleSize(int cx, int cy){ ClientRect clnt_rect(_hwnd); SIZE new_size = {cx, cy};
int dx = new_size.cx - _last_size.cx; int dy = new_size.cy - _last_size.cy;
if (!dx && !dy) return;
_last_size = new_size;
HDWP hDWP = BeginDeferWindowPos(size());
for(ResizeManager::const_iterator it=begin(); it!=end(); ++it) { const ResizeEntry& e = *it; RECT move = {0};
if (e._flags & MOVE_LEFT) move.left += dx;
if (e._flags & MOVE_RIGHT) move.right += dx;
if (e._flags & MOVE_TOP) move.top += dy;
if (e._flags & MOVE_BOTTOM) move.bottom += dy;
UINT flags = 0;
if (!move.left && !move.top) flags = SWP_NOMOVE;
if (move.right==move.left && move.bottom==move.top) flags |= SWP_NOSIZE;
if (flags != (SWP_NOMOVE|SWP_NOSIZE)) { HWND hwnd = GetDlgItem(_hwnd, e._id);
if (hwnd) { WindowRect rect(hwnd); ScreenToClient(_hwnd, rect);
rect.left += move.left; rect.right += move.right; rect.top += move.top; rect.bottom += move.bottom;
hDWP = DeferWindowPos(hDWP, hwnd, 0, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, flags|SWP_NOACTIVATE|SWP_NOZORDER); } } }
EndDeferWindowPos(hDWP);}
void ResizeManager::Resize(int dx, int dy){ ::SetWindowPos(_hwnd, 0, 0, 0, _min_wnd_size.cx+dx, _min_wnd_size.cy+dy, SWP_NOMOVE|SWP_NOACTIVATE); MoveVisible(_hwnd);
ClientRect clnt_rect(_hwnd); HandleSize(clnt_rect.right, clnt_rect.bottom);}
Button::Button(HWND parent, LPCTSTR title, int left, int top, int width, int height, int id, DWORD flags, DWORD exStyle) : WindowHandle(CreateWindowEx(exStyle, TEXT("BUTTON"), title, flags, left, top, width, height, parent, (HMENU)id, g_Globals._hInstance, 0)){}
LRESULT OwnerdrawnButton::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam){ if (nmsg == PM_DISPATCH_DRAWITEM) { DrawItem((LPDRAWITEMSTRUCT)lparam); return TRUE; } else return super::WndProc(nmsg, wparam, lparam);}
Static::Static(HWND parent, LPCTSTR title, int left, int top, int width, int height, int id, DWORD flags, DWORD exStyle) : WindowHandle(CreateWindowEx(exStyle, TEXT("STATIC"), title, flags, left, top, width, height, parent, (HMENU)id, g_Globals._hInstance, 0)){}
static RECT s_MyDrawText_Rect = {0, 0, 0, 0};
static BOOL CALLBACK MyDrawText(HDC hdc, LPARAM data, int cnt){ ::DrawText(hdc, (LPCTSTR)data, cnt, &s_MyDrawText_Rect, DT_SINGLELINE); return TRUE;}
void DrawGrayText(HDC hdc, LPRECT pRect, LPCTSTR title, int dt_flags){ COLORREF gray = GetSysColor(COLOR_GRAYTEXT);
if (gray) { TextColor lcColor(hdc, GetSysColor(COLOR_BTNHIGHLIGHT)); RECT shadowRect = {pRect->left+1, pRect->top+1, pRect->right+1, pRect->bottom+1}; DrawText(hdc, title, -1, &shadowRect, dt_flags);
SetTextColor(hdc, gray); DrawText(hdc, title, -1, pRect, dt_flags); } else { int old_r = pRect->right; int old_b = pRect->bottom;
DrawText(hdc, title, -1, pRect, dt_flags|DT_CALCRECT);
int x = pRect->left + (old_r-pRect->right)/2; int y = pRect->top + (old_b-pRect->bottom)/2; int w = pRect->right-pRect->left; int h = pRect->bottom-pRect->top; s_MyDrawText_Rect.right = w; s_MyDrawText_Rect.bottom = h;
GrayString(hdc, GetSysColorBrush(COLOR_GRAYTEXT), MyDrawText, (LPARAM)title, -1, x, y, w, h); }}
/* not yet usedvoid ColorButton::DrawItem(LPDRAWITEMSTRUCT dis){ UINT state = DFCS_BUTTONPUSH;
if (dis->itemState & ODS_DISABLED) state |= DFCS_INACTIVE;
RECT textRect = {dis->rcItem.left+2, dis->rcItem.top+2, dis->rcItem.right-4, dis->rcItem.bottom-4};
if (dis->itemState & ODS_SELECTED) { state |= DFCS_PUSHED; ++textRect.left; ++textRect.top; ++textRect.right; ++textRect.bottom; }
DrawFrameControl(dis->hDC, &dis->rcItem, DFC_BUTTON, state);
TCHAR title[BUFFER_LEN]; GetWindowText(_hwnd, title, BUFFER_LEN);
BkMode bk_mode(dis->hDC, TRANSPARENT);
if (dis->itemState & (ODS_DISABLED|ODS_GRAYED)) DrawGrayText(dis, &textRect, title, DT_SINGLELINE|DT_VCENTER|DT_CENTER); else { TextColor lcColor(dis->hDC, _textColor); DrawText(dis->hDC, title, -1, &textRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER); }
if (dis->itemState & ODS_FOCUS) { RECT rect = { dis->rcItem.left+3, dis->rcItem.top+3, dis->rcItem.right-dis->rcItem.left-4, dis->rcItem.bottom-dis->rcItem.top-4 }; if (dis->itemState & ODS_SELECTED) { ++rect.left; ++rect.top; ++rect.right; ++rect.bottom; } DrawFocusRect(dis->hDC, &rect); }}*/
void PictureButton::DrawItem(LPDRAWITEMSTRUCT dis){ UINT state = DFCS_BUTTONPUSH; int style = GetWindowStyle(_hwnd);
if (dis->itemState & ODS_DISABLED) state |= DFCS_INACTIVE;
POINT imagePos; RECT textRect; int dt_flags;
if (style & BS_BOTTOM) { // align horizontal centered, vertical floating imagePos.x = (dis->rcItem.left + dis->rcItem.right - _cx) / 2; imagePos.y = dis->rcItem.top + 3;
textRect.left = dis->rcItem.left + 2; textRect.top = dis->rcItem.top + _cy + 4; textRect.right = dis->rcItem.right - 4; textRect.bottom = dis->rcItem.bottom - 4;
dt_flags = DT_SINGLELINE|DT_CENTER|DT_VCENTER; } else { // horizontal floating, vertical centered imagePos.x = dis->rcItem.left + 3; imagePos.y = (dis->rcItem.top + dis->rcItem.bottom - _cy)/2;
textRect.left = dis->rcItem.left + _cx + 4; textRect.top = dis->rcItem.top + 2; textRect.right = dis->rcItem.right - 4; textRect.bottom = dis->rcItem.bottom - 4;
dt_flags = DT_SINGLELINE|DT_VCENTER/*|DT_CENTER*/; }
if (dis->itemState & ODS_SELECTED) { state |= DFCS_PUSHED; ++imagePos.x; ++imagePos.y; ++textRect.left; ++textRect.top; ++textRect.right; ++textRect.bottom; }
if (_flat) { FillRect(dis->hDC, &dis->rcItem, _hBrush);
if (style & BS_FLAT) // Only with BS_FLAT set, there will be drawn a frame without highlight. DrawEdge(dis->hDC, &dis->rcItem, EDGE_RAISED, BF_RECT|BF_FLAT); } else DrawFrameControl(dis->hDC, &dis->rcItem, DFC_BUTTON, state);
if (_hIcon) DrawIconEx(dis->hDC, imagePos.x, imagePos.y, _hIcon, _cx, _cy, 0, _hBrush, DI_NORMAL); else { MemCanvas mem_dc; BitmapSelection sel(mem_dc, _hBmp); BitBlt(dis->hDC, imagePos.x, imagePos.y, _cx, _cy, mem_dc, 0, 0, SRCCOPY); }
TCHAR title[BUFFER_LEN]; GetWindowText(_hwnd, title, BUFFER_LEN);
BkMode bk_mode(dis->hDC, TRANSPARENT);
if (dis->itemState & (ODS_DISABLED|ODS_GRAYED)) DrawGrayText(dis->hDC, &textRect, title, dt_flags); else { TextColor lcColor(dis->hDC, GetSysColor(COLOR_BTNTEXT)); DrawText(dis->hDC, title, -1, &textRect, dt_flags); }
if (dis->itemState & ODS_FOCUS) { RECT rect = { dis->rcItem.left+3, dis->rcItem.top+3, dis->rcItem.right-dis->rcItem.left-4, dis->rcItem.bottom-dis->rcItem.top-4 }; if (dis->itemState & ODS_SELECTED) { ++rect.left; ++rect.top; ++rect.right; ++rect.bottom; } DrawFocusRect(dis->hDC, &rect); }}
void FlatButton::DrawItem(LPDRAWITEMSTRUCT dis){ UINT style = DFCS_BUTTONPUSH;
if (dis->itemState & ODS_DISABLED) style |= DFCS_INACTIVE;
RECT textRect = {dis->rcItem.left+2, dis->rcItem.top+2, dis->rcItem.right-4, dis->rcItem.bottom-4};
if (dis->itemState & ODS_SELECTED) { style |= DFCS_PUSHED; ++textRect.left; ++textRect.top; ++textRect.right; ++textRect.bottom; }
FillRect(dis->hDC, &dis->rcItem, GetSysColorBrush(COLOR_BTNFACE));
// highlight the button? if (_active) DrawEdge(dis->hDC, &dis->rcItem, EDGE_ETCHED, BF_RECT); else if (GetWindowStyle(_hwnd) & BS_FLAT) // Only with BS_FLAT there will be drawn a frame to show highlighting. DrawEdge(dis->hDC, &dis->rcItem, EDGE_RAISED, BF_RECT|BF_FLAT);
TCHAR txt[BUFFER_LEN]; int txt_len = GetWindowText(_hwnd, txt, BUFFER_LEN);
if (dis->itemState & (ODS_DISABLED|ODS_GRAYED)) { COLORREF gray = GetSysColor(COLOR_GRAYTEXT);
if (gray) { { TextColor lcColor(dis->hDC, GetSysColor(COLOR_BTNHIGHLIGHT)); RECT shadowRect = {textRect.left+1, textRect.top+1, textRect.right+1, textRect.bottom+1}; DrawText(dis->hDC, txt, txt_len, &shadowRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER); }
BkMode mode(dis->hDC, TRANSPARENT); TextColor lcColor(dis->hDC, gray); DrawText(dis->hDC, txt, txt_len, &textRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER); } else { int old_r = textRect.right; int old_b = textRect.bottom; DrawText(dis->hDC, txt, txt_len, &textRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER|DT_CALCRECT); int x = textRect.left + (old_r-textRect.right)/2; int y = textRect.top + (old_b-textRect.bottom)/2; int w = textRect.right-textRect.left; int h = textRect.bottom-textRect.top; s_MyDrawText_Rect.right = w; s_MyDrawText_Rect.bottom = h; GrayString(dis->hDC, GetSysColorBrush(COLOR_GRAYTEXT), MyDrawText, (LPARAM)txt, txt_len, x, y, w, h); } } else { TextColor lcColor(dis->hDC, _active? _activeColor: _textColor); DrawText(dis->hDC, txt, txt_len, &textRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER); }
if (dis->itemState & ODS_FOCUS) { RECT rect = { dis->rcItem.left+3, dis->rcItem.top+3, dis->rcItem.right-dis->rcItem.left-4, dis->rcItem.bottom-dis->rcItem.top-4 }; if (dis->itemState & ODS_SELECTED) { ++rect.left; ++rect.top; ++rect.right; ++rect.bottom; } DrawFocusRect(dis->hDC, &rect); }}
LRESULT FlatButton::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam){ switch(nmsg) { case WM_MOUSEMOVE: { bool active = false;
if (IsWindowEnabled(_hwnd)) { DWORD pid_foreground; HWND hwnd_foreground = GetForegroundWindow(); //@@ may be better look for WM_ACTIVATEAPP ? GetWindowThreadProcessId(hwnd_foreground, &pid_foreground);
if (GetCurrentProcessId() == pid_foreground) { POINT pt = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)}; ClientRect clntRect(_hwnd);
// highlight the button? if (pt.x>=clntRect.left && pt.x<clntRect.right && pt.y>=clntRect.top && pt.y<clntRect.bottom) active = true; } }
if (active != _active) { _active = active;
if (active) { TRACKMOUSEEVENT tme = {sizeof(tme), /*TME_HOVER|*/TME_LEAVE, _hwnd/*, HOVER_DEFAULT*/}; _TrackMouseEvent(&tme); }
InvalidateRect(_hwnd, NULL, TRUE); }
return 0;}
case WM_LBUTTONUP: { POINT pt = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)}; ClientRect clntRect(_hwnd);
// no more in the active rectangle? if (pt.x<clntRect.left || pt.x>=clntRect.right || pt.y<clntRect.top || pt.y>=clntRect.bottom) goto cancel_press;
goto def;}
case WM_CANCELMODE: cancel_press: { TRACKMOUSEEVENT tme = {sizeof(tme), /*TME_HOVER|*/TME_LEAVE|TME_CANCEL, _hwnd/*, HOVER_DEFAULT*/}; _TrackMouseEvent(&tme); _active = false; ReleaseCapture();} // fall through
case WM_MOUSELEAVE: if (_active) { _active = false;
InvalidateRect(_hwnd, NULL, TRUE); }
return 0;
default: def: return super::WndProc(nmsg, wparam, lparam); }}
HyperlinkCtrl::HyperlinkCtrl(HWND hwnd, COLORREF colorLink, COLORREF colorVisited) : super(hwnd), _cmd(ResString(GetDlgCtrlID(hwnd))), _textColor(colorLink), _colorVisited(colorVisited), _hfont(0), _crsr_link(0){ init();}
HyperlinkCtrl::HyperlinkCtrl(HWND owner, int id, COLORREF colorLink, COLORREF colorVisited) : super(GetDlgItem(owner, id)), _cmd(ResString(id)), _textColor(colorLink), _colorVisited(colorVisited), _hfont(0), _crsr_link(0){ init();}
void HyperlinkCtrl::init(){ if (_cmd.empty()) { TCHAR txt[BUFFER_LEN]; _cmd.assign(txt, GetWindowText(_hwnd, txt, BUFFER_LEN)); }}
HyperlinkCtrl::~HyperlinkCtrl(){ if (_hfont) DeleteObject(_hfont);}
LRESULT HyperlinkCtrl::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam){ switch(nmsg) { case PM_DISPATCH_CTLCOLOR: { if (!_hfont) { HFONT hfont = (HFONT) SendMessage(_hwnd, WM_GETFONT, 0, 0); LOGFONT lf; GetObject(hfont, sizeof(lf), &lf); lf.lfUnderline = TRUE; _hfont = CreateFontIndirect(&lf); }
HDC hdc = (HDC) wparam; SetTextColor(hdc, _textColor); //@@ SelectFont(hdc, _hfont); SetBkMode(hdc, TRANSPARENT); return (LRESULT)GetStockObject(HOLLOW_BRUSH); }
case WM_SETCURSOR: if (!_crsr_link) _crsr_link = LoadCursor(0, IDC_HAND);
if (_crsr_link) SetCursor(_crsr_link); return 0;
case WM_NCHITTEST: return HTCLIENT; // Aktivierung von Maus-Botschaften
case WM_LBUTTONDOWN: if (LaunchLink()) { _textColor = _colorVisited; InvalidateRect(_hwnd, NULL, FALSE); } else MessageBeep(0); return 0;
default: return super::WndProc(nmsg, wparam, lparam); }}
ToolTip::ToolTip(HWND owner) : super(CreateWindowEx(WS_EX_TOPMOST|WS_EX_NOPARENTNOTIFY, TOOLTIPS_CLASS, 0, WS_POPUP|TTS_NOPREFIX|TTS_ALWAYSTIP, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, owner, 0, g_Globals._hInstance, 0)){ activate();}
ListSort::ListSort(HWND hwndListview, PFNLVCOMPARE compare_fct) : WindowHandle(hwndListview), _compare_fct(compare_fct){ _sort_crit = 0; _direction = false;}
void ListSort::toggle_sort(int idx){ if (_sort_crit == idx) _direction = !_direction; else { _sort_crit = idx; _direction = false; }}
void ListSort::sort(){ int idx = ListView_GetSelectionMark(_hwnd); LPARAM param = ListView_GetItemData(_hwnd, idx);
ListView_SortItems(_hwnd, _compare_fct, (LPARAM)this);
if (idx >= 0) { idx = ListView_FindItemPara(_hwnd, param); ListView_EnsureVisible(_hwnd, idx, FALSE); }}
PropSheetPage::PropSheetPage(UINT nid, Window::CREATORFUNC dlg_creator) : _dlg_creator(dlg_creator){ PROPSHEETPAGE::dwSize = sizeof(PROPSHEETPAGE); PROPSHEETPAGE::dwFlags = 0; PROPSHEETPAGE::hInstance = g_Globals._hInstance; PROPSHEETPAGE::pszTemplate = MAKEINTRESOURCE(nid); PROPSHEETPAGE::pfnDlgProc = PropSheetPageDlg::DialogProc; PROPSHEETPAGE::lParam = (LPARAM) this;}
#ifndef PSM_GETRESULT // currently (as of 18.01.2004) missing in MinGW headers#define PSM_GETRESULT (WM_USER + 135)#define PropSheet_GetResult(hDlg) SNDMSG(hDlg, PSM_GETRESULT, 0, 0)#endif
PropertySheetDialog::PropertySheetDialog(HWND owner) : _hwnd(0){ PROPSHEETHEADER::dwSize = sizeof(PROPSHEETHEADER); PROPSHEETHEADER::dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS; PROPSHEETHEADER::hwndParent = owner; PROPSHEETHEADER::hInstance = g_Globals._hInstance;}
void PropertySheetDialog::add(PropSheetPage& psp){ _pages.push_back(psp);}
int PropertySheetDialog::DoModal(int start_page){ PROPSHEETHEADER::ppsp = (LPCPROPSHEETPAGE) &_pages[0]; PROPSHEETHEADER::nPages = _pages.size(); PROPSHEETHEADER::nStartPage = start_page;/* Window* pwnd = Window::create_property_sheet(this, WINDOW_CREATOR(PropertySheetDlg), NULL); if (!pwnd) return -1;
HWND hwndPropSheet = *pwnd;*/ int ret = PropertySheet(this); if (ret == -1) return -1;
HWND hwndPropSheet = (HWND) ret; HWND hwndparent = GetParent(hwndPropSheet);
if (hwndparent) EnableWindow(hwndparent, FALSE);
ret = 0; MSG msg;
while(GetMessage(&msg, 0, 0, 0)) { try { if (Window::pretranslate_msg(&msg)) continue;
if (PropSheet_IsDialogMessage(hwndPropSheet, &msg)) continue;
if (Window::dispatch_dialog_msg(&msg)) continue;
TranslateMessage(&msg);
try { DispatchMessage(&msg); } catch(COMException& e) { HandleException(e, 0); }
if (!PropSheet_GetCurrentPageHwnd(hwndPropSheet)) { ret = PropSheet_GetResult(hwndPropSheet); break; } } catch(COMException& e) { HandleException(e, 0); } }
if (hwndparent) EnableWindow(hwndparent, TRUE);
DestroyWindow(hwndPropSheet);
return ret;}
HWND PropertySheetDialog::GetCurrentPage(){ HWND hdlg = PropSheet_GetCurrentPageHwnd(_hwnd); return hdlg;}
PropSheetPageDlg::PropSheetPageDlg(HWND hwnd) : super(hwnd){}
INT_PTR CALLBACK PropSheetPageDlg::DialogProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam){ PropSheetPageDlg* pThis = GET_WINDOW(PropSheetPageDlg, hwnd);
if (pThis) { switch(nmsg) { case WM_COMMAND: pThis->Command(LOWORD(wparam), HIWORD(wparam)); return TRUE; // message has been processed
case WM_NOTIFY: pThis->Notify(wparam, (NMHDR*)lparam); return TRUE; // message has been processed
case WM_NOTIFYFORMAT: SetWindowLongPtr(hwnd, DWLP_MSGRESULT, NFR_CURRENT); // set return value NFR_CURRENT return TRUE; // message has been processed
case WM_NCDESTROY: delete pThis; return TRUE; // message has been processed
default: return pThis->WndProc(nmsg, wparam, lparam); } } else if (nmsg == WM_INITDIALOG) { PROPSHEETPAGE* psp = (PROPSHEETPAGE*) lparam; PropSheetPage* ppsp = (PropSheetPage*) psp->lParam;
if (ppsp->_dlg_creator) { pThis = static_cast<PropSheetPageDlg*>(ppsp->_dlg_creator(hwnd));
if (pThis) return pThis->Init(NULL); } }
return FALSE; // message has not been processed}
int PropSheetPageDlg::Command(int id, int code){ // override call to EndDialog in Dialog::Command();
return FALSE;}