| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947 |
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
- #include "stdafx.h"
- #ifndef _AFX_NO_OCC_SUPPORT
- #include "occimpl.h"
- #endif
- #pragma warning(disable:4706)
- #define COMPILE_MULTIMON_STUBS
- #include <multimon.h>
- #pragma warning(default:4706)
- #ifdef AFX_CORE1_SEG
- #pragma code_seg(AFX_CORE1_SEG)
- #endif
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- #define new DEBUG_NEW
- /////////////////////////////////////////////////////////////////////////////
- // Globals
- const UINT CWnd::m_nMsgDragList = ::RegisterWindowMessage(DRAGLISTMSGSTRING);
- // CWnds for setting z-order with SetWindowPos's pWndInsertAfter parameter
- const AFX_DATADEF CWnd CWnd::wndTop(HWND_TOP);
- const AFX_DATADEF CWnd CWnd::wndBottom(HWND_BOTTOM);
- const AFX_DATADEF CWnd CWnd::wndTopMost(HWND_TOPMOST);
- const AFX_DATADEF CWnd CWnd::wndNoTopMost(HWND_NOTOPMOST);
- const TCHAR _afxWnd[] = AFX_WND;
- const TCHAR _afxWndControlBar[] = AFX_WNDCONTROLBAR;
- const TCHAR _afxWndMDIFrame[] = AFX_WNDMDIFRAME;
- const TCHAR _afxWndFrameOrView[] = AFX_WNDFRAMEORVIEW;
- const TCHAR _afxWndOleControl[] = AFX_WNDOLECONTROL;
- /////////////////////////////////////////////////////////////////////////////
- // CWnd construction
- CWnd::CWnd()
- {
- AFX_ZERO_INIT_OBJECT(CCmdTarget);
- }
- CWnd::CWnd(HWND hWnd)
- {
- AFX_ZERO_INIT_OBJECT(CCmdTarget);
- m_hWnd = hWnd;
- }
- // Change a window's style
- AFX_STATIC BOOL AFXAPI _AfxModifyStyle(HWND hWnd, int nStyleOffset,
- DWORD dwRemove, DWORD dwAdd, UINT nFlags)
- {
- ASSERT(hWnd != NULL);
- DWORD dwStyle = ::GetWindowLong(hWnd, nStyleOffset);
- DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
- if (dwStyle == dwNewStyle)
- return FALSE;
- ::SetWindowLong(hWnd, nStyleOffset, dwNewStyle);
- if (nFlags != 0)
- {
- ::SetWindowPos(hWnd, NULL, 0, 0, 0, 0,
- SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
- }
- return TRUE;
- }
- BOOL PASCAL
- CWnd::ModifyStyle(HWND hWnd, DWORD dwRemove, DWORD dwAdd, UINT nFlags)
- {
- return _AfxModifyStyle(hWnd, GWL_STYLE, dwRemove, dwAdd, nFlags);
- }
- BOOL PASCAL
- CWnd::ModifyStyleEx(HWND hWnd, DWORD dwRemove, DWORD dwAdd, UINT nFlags)
- {
- return _AfxModifyStyle(hWnd, GWL_EXSTYLE, dwRemove, dwAdd, nFlags);
- }
- /////////////////////////////////////////////////////////////////////////////
- // Special helpers for certain windows messages
- AFX_STATIC void AFXAPI _AfxPreInitDialog(
- CWnd* pWnd, LPRECT lpRectOld, DWORD* pdwStyleOld)
- {
- ASSERT(lpRectOld != NULL);
- ASSERT(pdwStyleOld != NULL);
- pWnd->GetWindowRect(lpRectOld);
- *pdwStyleOld = pWnd->GetStyle();
- }
- AFX_STATIC void AFXAPI _AfxPostInitDialog(
- CWnd* pWnd, const RECT& rectOld, DWORD dwStyleOld)
- {
- // must be hidden to start with
- if (dwStyleOld & WS_VISIBLE)
- return;
- // must not be visible after WM_INITDIALOG
- if (pWnd->GetStyle() & (WS_VISIBLE|WS_CHILD))
- return;
- // must not move during WM_INITDIALOG
- CRect rect;
- pWnd->GetWindowRect(rect);
- if (rectOld.left != rect.left || rectOld.top != rect.top)
- return;
- // must be unowned or owner disabled
- CWnd* pParent = pWnd->GetWindow(GW_OWNER);
- if (pParent != NULL && pParent->IsWindowEnabled())
- return;
- if (!pWnd->CheckAutoCenter())
- return;
- // center modal dialog boxes/message boxes
- pWnd->CenterWindow();
- }
- AFX_STATIC void AFXAPI
- _AfxHandleActivate(CWnd* pWnd, WPARAM nState, CWnd* pWndOther)
- {
- ASSERT(pWnd != NULL);
- // send WM_ACTIVATETOPLEVEL when top-level parents change
- CWnd* pTopLevel;
- if (!(pWnd->GetStyle() & WS_CHILD) &&
- (pTopLevel = pWnd->GetTopLevelParent()) != pWndOther->GetTopLevelParent())
- {
- // lParam points to window getting the WM_ACTIVATE message and
- // hWndOther from the WM_ACTIVATE.
- HWND hWnd2[2];
- hWnd2[0] = pWnd->m_hWnd;
- hWnd2[1] = pWndOther->GetSafeHwnd();
- // send it...
- pTopLevel->SendMessage(WM_ACTIVATETOPLEVEL, nState, (LPARAM)&hWnd2[0]);
- }
- }
- AFX_STATIC BOOL AFXAPI
- _AfxHandleSetCursor(CWnd* pWnd, UINT nHitTest, UINT nMsg)
- {
- if (nHitTest == HTERROR &&
- (nMsg == WM_LBUTTONDOWN || nMsg == WM_MBUTTONDOWN ||
- nMsg == WM_RBUTTONDOWN))
- {
- // activate the last active window if not active
- CWnd* pLastActive = pWnd->GetTopLevelParent();
- if (pLastActive != NULL)
- pLastActive = pLastActive->GetLastActivePopup();
- if (pLastActive != NULL &&
- pLastActive != CWnd::GetForegroundWindow() &&
- pLastActive->IsWindowEnabled())
- {
- pLastActive->SetForegroundWindow();
- return TRUE;
- }
- }
- return FALSE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Official way to send message to a CWnd
- LRESULT AFXAPI AfxCallWndProc(CWnd* pWnd, HWND hWnd, UINT nMsg,
- WPARAM wParam = 0, LPARAM lParam = 0)
- {
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- MSG oldState = pThreadState->m_lastSentMsg; // save for nesting
- pThreadState->m_lastSentMsg.hwnd = hWnd;
- pThreadState->m_lastSentMsg.message = nMsg;
- pThreadState->m_lastSentMsg.wParam = wParam;
- pThreadState->m_lastSentMsg.lParam = lParam;
- #ifdef _DEBUG
- if (afxTraceFlags & traceWinMsg)
- _AfxTraceMsg(_T("WndProc"), &pThreadState->m_lastSentMsg);
- #endif
- // Catch exceptions thrown outside the scope of a callback
- // in debug builds and warn the user.
- LRESULT lResult;
- TRY
- {
- #ifndef _AFX_NO_OCC_SUPPORT
- // special case for WM_DESTROY
- if ((nMsg == WM_DESTROY) && (pWnd->m_pCtrlCont != NULL))
- pWnd->m_pCtrlCont->OnUIActivate(NULL);
- #endif
- // special case for WM_INITDIALOG
- CRect rectOld;
- DWORD dwStyle = 0;
- if (nMsg == WM_INITDIALOG)
- _AfxPreInitDialog(pWnd, &rectOld, &dwStyle);
- // delegate to object's WindowProc
- lResult = pWnd->WindowProc(nMsg, wParam, lParam);
- // more special case for WM_INITDIALOG
- if (nMsg == WM_INITDIALOG)
- _AfxPostInitDialog(pWnd, rectOld, dwStyle);
- }
- CATCH_ALL(e)
- {
- lResult = AfxGetThread()->ProcessWndProcException(e, &pThreadState->m_lastSentMsg);
- TRACE1("Warning: Uncaught exception in WindowProc (returning %ld).\n",
- lResult);
- DELETE_EXCEPTION(e);
- }
- END_CATCH_ALL
- pThreadState->m_lastSentMsg = oldState;
- return lResult;
- }
- const MSG* PASCAL CWnd::GetCurrentMessage()
- {
- // fill in time and position when asked for
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- pThreadState->m_lastSentMsg.time = ::GetMessageTime();
- pThreadState->m_lastSentMsg.pt = CPoint(::GetMessagePos());
- return &pThreadState->m_lastSentMsg;
- }
- LRESULT CWnd::Default()
- {
- // call DefWindowProc with the last message
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- return DefWindowProc(pThreadState->m_lastSentMsg.message,
- pThreadState->m_lastSentMsg.wParam, pThreadState->m_lastSentMsg.lParam);
- }
- /////////////////////////////////////////////////////////////////////////////
- // Map from HWND to CWnd*
- #include "fixalloc.h"
- class CTempWnd : public CWnd
- {
- DECLARE_DYNCREATE(CTempWnd)
- DECLARE_FIXED_ALLOC(CTempWnd);
- };
- CHandleMap* PASCAL afxMapHWND(BOOL bCreate)
- {
- AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
- if (pState->m_pmapHWND == NULL && bCreate)
- {
- BOOL bEnable = AfxEnableMemoryTracking(FALSE);
- #ifndef _AFX_PORTABLE
- _PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler);
- #endif
- pState->m_pmapHWND = new CHandleMap(RUNTIME_CLASS(CTempWnd),
- offsetof(CWnd, m_hWnd));
- #ifndef _AFX_PORTABLE
- AfxSetNewHandler(pnhOldHandler);
- #endif
- AfxEnableMemoryTracking(bEnable);
- }
- return pState->m_pmapHWND;
- }
- CWnd* PASCAL CWnd::FromHandle(HWND hWnd)
- {
- CHandleMap* pMap = afxMapHWND(TRUE); //create map if not exist
- ASSERT(pMap != NULL);
- CWnd* pWnd = (CWnd*)pMap->FromHandle(hWnd);
- #ifndef _AFX_NO_OCC_SUPPORT
- pWnd->AttachControlSite(pMap);
- #endif
- ASSERT(pWnd == NULL || pWnd->m_hWnd == hWnd);
- return pWnd;
- }
- CWnd* PASCAL CWnd::FromHandlePermanent(HWND hWnd)
- {
- CHandleMap* pMap = afxMapHWND();
- CWnd* pWnd = NULL;
- if (pMap != NULL)
- {
- // only look in the permanent map - does no allocations
- pWnd = (CWnd*)pMap->LookupPermanent(hWnd);
- ASSERT(pWnd == NULL || pWnd->m_hWnd == hWnd);
- }
- return pWnd;
- }
- BOOL CWnd::Attach(HWND hWndNew)
- {
- ASSERT(m_hWnd == NULL); // only attach once, detach on destroy
- ASSERT(FromHandlePermanent(hWndNew) == NULL);
- // must not already be in permanent map
- if (hWndNew == NULL)
- return FALSE;
- CHandleMap* pMap = afxMapHWND(TRUE); // create map if not exist
- ASSERT(pMap != NULL);
- pMap->SetPermanent(m_hWnd = hWndNew, this);
- #ifndef _AFX_NO_OCC_SUPPORT
- AttachControlSite(pMap);
- #endif
- return TRUE;
- }
- HWND CWnd::Detach()
- {
- HWND hWnd = m_hWnd;
- if (hWnd != NULL)
- {
- CHandleMap* pMap = afxMapHWND(); // don't create if not exist
- if (pMap != NULL)
- pMap->RemoveHandle(m_hWnd);
- m_hWnd = NULL;
- }
- #ifndef _AFX_NO_OCC_SUPPORT
- m_pCtrlSite = NULL;
- #endif
- return hWnd;
- }
- void CWnd::PreSubclassWindow()
- {
- // no default processing
- }
- /////////////////////////////////////////////////////////////////////////////
- // The WndProc for all CWnd's and derived classes
- LRESULT CALLBACK
- AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
- {
- // special message which identifies the window as using AfxWndProc
- if (nMsg == WM_QUERYAFXWNDPROC)
- return 1;
- // all other messages route through message map
- CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
- ASSERT(pWnd != NULL);
- ASSERT(pWnd->m_hWnd == hWnd);
- return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);
- }
- // always indirectly accessed via AfxGetAfxWndProc
- WNDPROC AFXAPI AfxGetAfxWndProc()
- {
- #ifdef _AFXDLL
- return AfxGetModuleState()->m_pfnAfxWndProc;
- #else
- return &AfxWndProc;
- #endif
- }
- /////////////////////////////////////////////////////////////////////////////
- // Special WndProcs (activation handling & gray dialogs)
- AFX_STATIC_DATA const TCHAR _afxOldWndProc[] = _T("AfxOldWndProc423");
- LRESULT CALLBACK
- _AfxActivationWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
- {
- WNDPROC oldWndProc = (WNDPROC)::GetProp(hWnd, _afxOldWndProc);
- ASSERT(oldWndProc != NULL);
- LRESULT lResult = 0;
- TRY
- {
- BOOL bCallDefault = TRUE;
- switch (nMsg)
- {
- case WM_INITDIALOG:
- {
- DWORD dwStyle;
- CRect rectOld;
- CWnd* pWnd = CWnd::FromHandle(hWnd);
- _AfxPreInitDialog(pWnd, &rectOld, &dwStyle);
- bCallDefault = FALSE;
- lResult = CallWindowProc(oldWndProc, hWnd, nMsg, wParam, lParam);
- _AfxPostInitDialog(pWnd, rectOld, dwStyle);
- }
- break;
- case WM_ACTIVATE:
- _AfxHandleActivate(CWnd::FromHandle(hWnd), wParam,
- CWnd::FromHandle((HWND)lParam));
- break;
- case WM_SETCURSOR:
- bCallDefault = !_AfxHandleSetCursor(CWnd::FromHandle(hWnd),
- (short)LOWORD(lParam), HIWORD(lParam));
- break;
- case WM_NCDESTROY:
- SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)oldWndProc);
- RemoveProp(hWnd, _afxOldWndProc);
- GlobalDeleteAtom(GlobalFindAtom(_afxOldWndProc));
- break;
- }
- // call original wndproc for default handling
- if (bCallDefault)
- lResult = CallWindowProc(oldWndProc, hWnd, nMsg, wParam, lParam);
- }
- CATCH_ALL(e)
- {
- // handle exception
- MSG msg;
- msg.hwnd = hWnd;
- msg.message = nMsg;
- msg.wParam = wParam;
- msg.lParam = lParam;
- lResult = AfxGetThread()->ProcessWndProcException(e, &msg);
- TRACE1("Warning: Uncaught exception in _AfxActivationWndProc (returning %ld).\n",
- lResult);
- DELETE_EXCEPTION(e);
- }
- END_CATCH_ALL
- return lResult;
- }
- #ifndef _AFX_NO_GRAYDLG_SUPPORT
- LRESULT CALLBACK
- _AfxGrayBackgroundWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
- {
- // handle standard gray backgrounds if enabled
- _AFX_WIN_STATE* pWinState = _afxWinState;
- if (pWinState->m_hDlgBkBrush != NULL &&
- (nMsg == WM_CTLCOLORBTN || nMsg == WM_CTLCOLORDLG ||
- nMsg == WM_CTLCOLORSTATIC || nMsg == WM_CTLCOLORSCROLLBAR ||
- nMsg == WM_CTLCOLORLISTBOX) &&
- CWnd::GrayCtlColor((HDC)wParam, (HWND)lParam,
- (UINT)(nMsg - WM_CTLCOLORMSGBOX),
- pWinState->m_hDlgBkBrush, pWinState->m_crDlgTextClr))
- {
- return (LRESULT)pWinState->m_hDlgBkBrush;
- }
- // do standard activation related things as well
- return _AfxActivationWndProc(hWnd, nMsg, wParam, lParam);
- }
- #else //!_AFX_NO_GRAYDLG_SUPPORT
- #define _AfxGrayBackgroundWndProc _AfxActivationWndProc
- #endif //_AFX_NO_GRAYDLG_SUPPORT
- /////////////////////////////////////////////////////////////////////////////
- // Window creation hooks
- LRESULT CALLBACK
- _AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam)
- {
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- if (code != HCBT_CREATEWND)
- {
- // wait for HCBT_CREATEWND just pass others on...
- return CallNextHookEx(pThreadState->m_hHookOldCbtFilter, code,
- wParam, lParam);
- }
- ASSERT(lParam != NULL);
- LPCREATESTRUCT lpcs = ((LPCBT_CREATEWND)lParam)->lpcs;
- ASSERT(lpcs != NULL);
- CWnd* pWndInit = pThreadState->m_pWndInit;
- BOOL bContextIsDLL = afxContextIsDLL;
- if (pWndInit != NULL || (!(lpcs->style & WS_CHILD) && !bContextIsDLL))
- {
- // Note: special check to avoid subclassing the IME window
- if (_afxDBCS)
- {
- // check for cheap CS_IME style first...
- if (GetClassLong((HWND)wParam, GCL_STYLE) & CS_IME)
- goto lCallNextHook;
- // get class name of the window that is being created
- LPCTSTR pszClassName;
- TCHAR szClassName[_countof("ime")+1];
- if (HIWORD(lpcs->lpszClass))
- {
- pszClassName = lpcs->lpszClass;
- }
- else
- {
- szClassName[0] = '\0';
- GlobalGetAtomName((ATOM)lpcs->lpszClass, szClassName, _countof(szClassName));
- pszClassName = szClassName;
- }
- // a little more expensive to test this way, but necessary...
- if (lstrcmpi(pszClassName, _T("ime")) == 0)
- goto lCallNextHook;
- }
- ASSERT(wParam != NULL); // should be non-NULL HWND
- HWND hWnd = (HWND)wParam;
- WNDPROC oldWndProc;
- if (pWndInit != NULL)
- {
- #ifdef _AFXDLL
- AFX_MANAGE_STATE(pWndInit->m_pModuleState);
- #endif
- // the window should not be in the permanent map at this time
- ASSERT(CWnd::FromHandlePermanent(hWnd) == NULL);
- // connect the HWND to pWndInit...
- pWndInit->Attach(hWnd);
- // allow other subclassing to occur first
- pWndInit->PreSubclassWindow();
- WNDPROC *pOldWndProc = pWndInit->GetSuperWndProcAddr();
- ASSERT(pOldWndProc != NULL);
- #ifndef _AFX_NO_CTL3D_SUPPORT
- _AFX_CTL3D_STATE* pCtl3dState;
- DWORD dwFlags;
- if (!afxData.bWin4 && !bContextIsDLL &&
- (pCtl3dState = _afxCtl3dState.GetDataNA()) != NULL &&
- pCtl3dState->m_pfnSubclassDlgEx != NULL &&
- (dwFlags = AfxCallWndProc(pWndInit, hWnd, WM_QUERY3DCONTROLS)) != 0)
- {
- // was the class registered with AfxWndProc?
- WNDPROC afxWndProc = AfxGetAfxWndProc();
- BOOL bAfxWndProc = ((WNDPROC)
- GetWindowLong(hWnd, GWL_WNDPROC) == afxWndProc);
- pCtl3dState->m_pfnSubclassDlgEx(hWnd, dwFlags);
- // subclass the window if not already wired to AfxWndProc
- if (!bAfxWndProc)
- {
- // subclass the window with standard AfxWndProc
- oldWndProc = (WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC,
- (DWORD)afxWndProc);
- ASSERT(oldWndProc != NULL);
- *pOldWndProc = oldWndProc;
- }
- }
- else
- #endif
- {
- // subclass the window with standard AfxWndProc
- WNDPROC afxWndProc = AfxGetAfxWndProc();
- oldWndProc = (WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC,
- (DWORD)afxWndProc);
- ASSERT(oldWndProc != NULL);
- if (oldWndProc != afxWndProc)
- *pOldWndProc = oldWndProc;
- }
- pThreadState->m_pWndInit = NULL;
- }
- else
- {
- ASSERT(!bContextIsDLL); // should never get here
- // subclass the window with the proc which does gray backgrounds
- oldWndProc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);
- if (oldWndProc != NULL && GetProp(hWnd, _afxOldWndProc) == NULL)
- {
- SetProp(hWnd, _afxOldWndProc, oldWndProc);
- if ((WNDPROC)GetProp(hWnd, _afxOldWndProc) == oldWndProc)
- {
- GlobalAddAtom(_afxOldWndProc);
- SetWindowLong(hWnd, GWL_WNDPROC,
- (DWORD)(pThreadState->m_bDlgCreate ?
- _AfxGrayBackgroundWndProc : _AfxActivationWndProc));
- ASSERT(oldWndProc != NULL);
- }
- }
- }
- }
- lCallNextHook:
- LRESULT lResult = CallNextHookEx(pThreadState->m_hHookOldCbtFilter, code,
- wParam, lParam);
- #ifndef _AFXDLL
- if (bContextIsDLL)
- {
- ::UnhookWindowsHookEx(pThreadState->m_hHookOldCbtFilter);
- pThreadState->m_hHookOldCbtFilter = NULL;
- }
- #endif
- return lResult;
- }
- void AFXAPI AfxHookWindowCreate(CWnd* pWnd)
- {
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- if (pThreadState->m_pWndInit == pWnd)
- return;
- if (pThreadState->m_hHookOldCbtFilter == NULL)
- {
- pThreadState->m_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT,
- _AfxCbtFilterHook, NULL, ::GetCurrentThreadId());
- if (pThreadState->m_hHookOldCbtFilter == NULL)
- AfxThrowMemoryException();
- }
- ASSERT(pThreadState->m_hHookOldCbtFilter != NULL);
- ASSERT(pWnd != NULL);
- ASSERT(pWnd->m_hWnd == NULL); // only do once
- ASSERT(pThreadState->m_pWndInit == NULL); // hook not already in progress
- pThreadState->m_pWndInit = pWnd;
- }
- BOOL AFXAPI AfxUnhookWindowCreate()
- {
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- #ifndef _AFXDLL
- if (afxContextIsDLL && pThreadState->m_hHookOldCbtFilter != NULL)
- {
- ::UnhookWindowsHookEx(pThreadState->m_hHookOldCbtFilter);
- pThreadState->m_hHookOldCbtFilter = NULL;
- }
- #endif
- if (pThreadState->m_pWndInit != NULL)
- {
- pThreadState->m_pWndInit = NULL;
- return FALSE; // was not successfully hooked
- }
- return TRUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CWnd creation
- BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
- LPCTSTR lpszWindowName, DWORD dwStyle,
- const RECT& rect, CWnd* pParentWnd, UINT nID,
- LPVOID lpParam /* = NULL */)
- {
- return CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
- rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
- pParentWnd->GetSafeHwnd(), (HMENU)nID, lpParam);
- }
- BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
- LPCTSTR lpszWindowName, DWORD dwStyle,
- int x, int y, int nWidth, int nHeight,
- HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
- {
- // allow modification of several common create parameters
- CREATESTRUCT cs;
- cs.dwExStyle = dwExStyle;
- cs.lpszClass = lpszClassName;
- cs.lpszName = lpszWindowName;
- cs.style = dwStyle;
- cs.x = x;
- cs.y = y;
- cs.cx = nWidth;
- cs.cy = nHeight;
- cs.hwndParent = hWndParent;
- cs.hMenu = nIDorHMenu;
- cs.hInstance = AfxGetInstanceHandle();
- cs.lpCreateParams = lpParam;
- if (!PreCreateWindow(cs))
- {
- PostNcDestroy();
- return FALSE;
- }
- AfxHookWindowCreate(this);
- HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,
- cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
- cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);
- #ifdef _DEBUG
- if (hWnd == NULL)
- {
- TRACE1("Warning: Window creation failed: GetLastError returns 0x%8.8X\n",
- GetLastError());
- }
- #endif
- if (!AfxUnhookWindowCreate())
- PostNcDestroy(); // cleanup if CreateWindowEx fails too soon
- if (hWnd == NULL)
- return FALSE;
- ASSERT(hWnd == m_hWnd); // should have been set in send msg hook
- return TRUE;
- }
- // for child windows
- BOOL CWnd::PreCreateWindow(CREATESTRUCT& cs)
- {
- if (cs.lpszClass == NULL)
- {
- // make sure the default window class is registered
- VERIFY(AfxDeferRegisterClass(AFX_WND_REG));
- // no WNDCLASS provided - use child window default
- ASSERT(cs.style & WS_CHILD);
- cs.lpszClass = _afxWnd;
- }
- return TRUE;
- }
- BOOL CWnd::Create(LPCTSTR lpszClassName,
- LPCTSTR lpszWindowName, DWORD dwStyle,
- const RECT& rect,
- CWnd* pParentWnd, UINT nID,
- CCreateContext* pContext)
- {
- // can't use for desktop or pop-up windows (use CreateEx instead)
- ASSERT(pParentWnd != NULL);
- ASSERT((dwStyle & WS_POPUP) == 0);
- return CreateEx(0, lpszClassName, lpszWindowName,
- dwStyle | WS_CHILD,
- rect.left, rect.top,
- rect.right - rect.left, rect.bottom - rect.top,
- pParentWnd->GetSafeHwnd(), (HMENU)nID, (LPVOID)pContext);
- }
- CWnd::~CWnd()
- {
- if (m_hWnd != NULL &&
- this != (CWnd*)&wndTop && this != (CWnd*)&wndBottom &&
- this != (CWnd*)&wndTopMost && this != (CWnd*)&wndNoTopMost)
- {
- TRACE(_T("Warning: calling DestroyWindow in CWnd::~CWnd; ")
- _T("OnDestroy or PostNcDestroy in derived class will not be called.\n"));
- DestroyWindow();
- }
- #ifndef _AFX_NO_OCC_SUPPORT
- // cleanup control container,
- // including destroying controls
- delete m_pCtrlCont;
- // cleanup control site
- if (m_pCtrlSite != NULL && m_pCtrlSite->m_pWndCtrl == this)
- m_pCtrlSite->m_pWndCtrl = NULL;
- #endif
- }
- void CWnd::OnDestroy()
- {
- #ifndef _AFX_NO_OCC_SUPPORT
- // cleanup control container
- delete m_pCtrlCont;
- m_pCtrlCont = NULL;
- #endif
- Default();
- }
- // WM_NCDESTROY is the absolute LAST message sent.
- void CWnd::OnNcDestroy()
- {
- // cleanup main and active windows
- CWinThread* pThread = AfxGetThread();
- if (pThread != NULL)
- {
- if (pThread->m_pMainWnd == this)
- {
- if (!afxContextIsDLL)
- {
- // shut down current thread if possible
- if (pThread != AfxGetApp() || AfxOleCanExitApp())
- AfxPostQuitMessage(0);
- }
- pThread->m_pMainWnd = NULL;
- }
- if (pThread->m_pActiveWnd == this)
- pThread->m_pActiveWnd = NULL;
- }
- #ifndef _AFX_NO_OLE_SUPPORT
- // cleanup OLE drop target interface
- if (m_pDropTarget != NULL)
- {
- m_pDropTarget->Revoke();
- m_pDropTarget = NULL;
- }
- #endif
- #ifndef _AFX_NO_OCC_SUPPORT
- // cleanup control container
- delete m_pCtrlCont;
- m_pCtrlCont = NULL;
- #endif
- // cleanup tooltip support
- if (m_nFlags & WF_TOOLTIPS)
- {
- CToolTipCtrl* pToolTip = AfxGetThreadState()->m_pToolTip;
- if (pToolTip->GetSafeHwnd() != NULL)
- {
- TOOLINFO ti; memset(&ti, 0, sizeof(TOOLINFO));
- ti.cbSize = sizeof(AFX_OLDTOOLINFO);
- ti.uFlags = TTF_IDISHWND;
- ti.hwnd = m_hWnd;
- ti.uId = (UINT)m_hWnd;
- pToolTip->SendMessage(TTM_DELTOOL, 0, (LPARAM)&ti);
- }
- }
- // call default, unsubclass, and detach from the map
- LONG pfnWndProc = GetWindowLong(m_hWnd, GWL_WNDPROC);
- Default();
- if (GetWindowLong(m_hWnd, GWL_WNDPROC) == pfnWndProc)
- {
- WNDPROC pfnSuper = *GetSuperWndProcAddr();
- if (pfnSuper != NULL)
- SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)pfnSuper);
- }
- Detach();
- ASSERT(m_hWnd == NULL);
- // call special post-cleanup routine
- PostNcDestroy();
- }
- void CWnd::PostNcDestroy()
- {
- // default to nothing
- }
- void CWnd::OnFinalRelease()
- {
- if (m_hWnd != NULL)
- DestroyWindow(); // will call PostNcDestroy
- else
- PostNcDestroy();
- }
- #ifdef _DEBUG
- void CWnd::AssertValid() const
- {
- if (m_hWnd == NULL)
- return; // null (unattached) windows are valid
- // check for special wnd??? values
- ASSERT(HWND_TOP == NULL); // same as desktop
- if (m_hWnd == HWND_BOTTOM)
- ASSERT(this == &CWnd::wndBottom);
- else if (m_hWnd == HWND_TOPMOST)
- ASSERT(this == &CWnd::wndTopMost);
- else if (m_hWnd == HWND_NOTOPMOST)
- ASSERT(this == &CWnd::wndNoTopMost);
- else
- {
- // should be a normal window
- ASSERT(::IsWindow(m_hWnd));
- // should also be in the permanent or temporary handle map
- CHandleMap* pMap = afxMapHWND();
- ASSERT(pMap != NULL);
- CObject* p;
- ASSERT((p = pMap->LookupPermanent(m_hWnd)) != NULL ||
- (p = pMap->LookupTemporary(m_hWnd)) != NULL);
- ASSERT((CWnd*)p == this); // must be us
- // Note: if either of the above asserts fire and you are
- // writing a multithreaded application, it is likely that
- // you have passed a C++ object from one thread to another
- // and have used that object in a way that was not intended.
- // (only simple inline wrapper functions should be used)
- //
- // In general, CWnd objects should be passed by HWND from
- // one thread to another. The receiving thread can wrap
- // the HWND with a CWnd object by using CWnd::FromHandle.
- //
- // It is dangerous to pass C++ objects from one thread to
- // another, unless the objects are designed to be used in
- // such a manner.
- }
- }
- void CWnd::Dump(CDumpContext& dc) const
- {
- CObject::Dump(dc);
- dc << "\nm_hWnd = " << (UINT)m_hWnd;
- if (m_hWnd == NULL || m_hWnd == HWND_BOTTOM ||
- m_hWnd == HWND_TOPMOST || m_hWnd == HWND_NOTOPMOST)
- {
- // not a normal window - nothing more to dump
- return;
- }
- if (!::IsWindow(m_hWnd))
- {
- // not a valid window
- dc << " (illegal HWND)";
- return; // don't do anything more
- }
- CWnd* pWnd = CWnd::FromHandlePermanent(m_hWnd);
- if (pWnd != this)
- dc << " (Detached or temporary window)";
- else
- dc << " (permanent window)";
- // dump out window specific statistics
- TCHAR szBuf [64];
- if (!::SendMessage(m_hWnd, WM_QUERYAFXWNDPROC, 0, 0) && pWnd == this)
- GetWindowText(szBuf, _countof(szBuf));
- else
- ::DefWindowProc(m_hWnd, WM_GETTEXT, _countof(szBuf), (LPARAM)&szBuf[0]);
- dc << "\ncaption = \"" << szBuf << "\"";
- ::GetClassName(m_hWnd, szBuf, _countof(szBuf));
- dc << "\nclass name = \"" << szBuf << "\"";
- CRect rect;
- GetWindowRect(&rect);
- dc << "\nrect = " << rect;
- dc << "\nparent CWnd* = " << (void*)GetParent();
- dc << "\nstyle = " << (void*)::GetWindowLong(m_hWnd, GWL_STYLE);
- if (::GetWindowLong(m_hWnd, GWL_STYLE) & WS_CHILD)
- dc << "\nid = " << _AfxGetDlgCtrlID(m_hWnd);
- dc << "\n";
- }
- #endif
- BOOL CWnd::DestroyWindow()
- {
- if (m_hWnd == NULL)
- return FALSE;
- CHandleMap* pMap = afxMapHWND();
- ASSERT(pMap != NULL);
- CWnd* pWnd = (CWnd*)pMap->LookupPermanent(m_hWnd);
- #ifdef _DEBUG
- HWND hWndOrig = m_hWnd;
- #endif
- #ifdef _AFX_NO_OCC_SUPPORT
- BOOL bResult = ::DestroyWindow(m_hWnd);
- #else //_AFX_NO_OCC_SUPPORT
- BOOL bResult;
- if (m_pCtrlSite == NULL)
- bResult = ::DestroyWindow(m_hWnd);
- else
- bResult = m_pCtrlSite->DestroyControl();
- #endif //_AFX_NO_OCC_SUPPORT
- // Note that 'this' may have been deleted at this point,
- // (but only if pWnd != NULL)
- if (pWnd != NULL)
- {
- // Should have been detached by OnNcDestroy
- #ifdef _DEBUG
- ASSERT(pMap->LookupPermanent(hWndOrig) == NULL);
- #endif
- }
- else
- {
- #ifdef _DEBUG
- ASSERT(m_hWnd == hWndOrig);
- #endif
- // Detach after DestroyWindow called just in case
- Detach();
- }
- return bResult;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Default CWnd implementation
- LRESULT CWnd::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
- {
- if (m_pfnSuper != NULL)
- return ::CallWindowProc(m_pfnSuper, m_hWnd, nMsg, wParam, lParam);
- WNDPROC pfnWndProc;
- if ((pfnWndProc = *GetSuperWndProcAddr()) == NULL)
- return ::DefWindowProc(m_hWnd, nMsg, wParam, lParam);
- else
- return ::CallWindowProc(pfnWndProc, m_hWnd, nMsg, wParam, lParam);
- }
- WNDPROC* CWnd::GetSuperWndProcAddr()
- {
- // Note: it is no longer necessary to override GetSuperWndProcAddr
- // for each control class with a different WNDCLASS.
- // This implementation now uses instance data, such that the previous
- // WNDPROC can be anything.
- return &m_pfnSuper;
- }
- BOOL CWnd::PreTranslateMessage(MSG* pMsg)
- {
- // handle tooltip messages (some messages cancel, some may cause it to popup)
- AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
- if (pModuleState->m_pfnFilterToolTipMessage != NULL)
- (*pModuleState->m_pfnFilterToolTipMessage)(pMsg, this);
- // no default processing
- return FALSE;
- }
- void PASCAL CWnd::CancelToolTips(BOOL bKeys)
- {
- // check for active tooltip
- _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
- CToolTipCtrl* pToolTip = pThreadState->m_pToolTip;
- if (pToolTip->GetSafeHwnd() != NULL)
- pToolTip->SendMessage(TTM_ACTIVATE, FALSE);
- // check for active control bar fly-by status
- CControlBar* pLastStatus = pThreadState->m_pLastStatus;
- if (bKeys && pLastStatus != NULL && GetKeyState(VK_LBUTTON) >= 0)
- pLastStatus->SetStatusText(-1);
- }
- int CWnd::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
- {
- // find child window which hits the point
- // (don't use WindowFromPoint, because it ignores disabled windows)
- HWND hWndChild = _AfxChildWindowFromPoint(m_hWnd, point);
- if (hWndChild != NULL)
- {
- // return positive hit if control ID isn't -1
- int nHit = _AfxGetDlgCtrlID(hWndChild);
- // hits against child windows always center the tip
- if (pTI != NULL && pTI->cbSize >= sizeof(AFX_OLDTOOLINFO))
- {
- // setup the TOOLINFO structure
- pTI->hwnd = m_hWnd;
- pTI->uId = (UINT)hWndChild;
- pTI->uFlags |= TTF_IDISHWND;
- pTI->lpszText = LPSTR_TEXTCALLBACK;
- // set TTF_NOTBUTTON and TTF_CENTERTIP if it isn't a button
- if (!(::SendMessage(hWndChild, WM_GETDLGCODE, 0, 0) & DLGC_BUTTON))
- pTI->uFlags |= TTF_NOTBUTTON|TTF_CENTERTIP;
- }
- return nHit;
- }
- return -1; // not found
- }
- void CWnd::GetWindowText(CString& rString) const
- {
- ASSERT(::IsWindow(m_hWnd));
- #ifndef _AFX_NO_OCC_SUPPORT
- if (m_pCtrlSite == NULL)
- {
- #endif
- int nLen = ::GetWindowTextLength(m_hWnd);
- ::GetWindowText(m_hWnd, rString.GetBufferSetLength(nLen), nLen+1);
- rString.ReleaseBuffer();
- #ifndef _AFX_NO_OCC_SUPPORT
- }
- else
- {
- m_pCtrlSite->GetWindowText(rString);
- }
- #endif
- }
- int CWnd::GetDlgItemText(int nID, CString& rString) const
- {
- ASSERT(::IsWindow(m_hWnd));
- rString = &afxChNil; // empty without deallocating
- #ifndef _AFX_NO_OCC_SUPPORT
- if (m_pCtrlCont == NULL)
- {
- #endif
- HWND hWnd = ::GetDlgItem(m_hWnd, nID);
- if (hWnd != NULL)
- {
- int nLen = ::GetWindowTextLength(hWnd);
- ::GetWindowText(hWnd, rString.GetBufferSetLength(nLen), nLen+1);
- rString.ReleaseBuffer();
- }
- #ifndef _AFX_NO_OCC_SUPPORT
- }
- else
- {
- CWnd* pWnd = GetDlgItem(nID);
- if (pWnd != NULL)
- pWnd->GetWindowText(rString);
- }
- #endif
- return rString.GetLength();
- }
- BOOL CWnd::GetWindowPlacement(WINDOWPLACEMENT* lpwndpl) const
- {
- ASSERT(::IsWindow(m_hWnd));
- lpwndpl->length = sizeof(WINDOWPLACEMENT);
- return ::GetWindowPlacement(m_hWnd, lpwndpl);
- }
- BOOL CWnd::SetWindowPlacement(const WINDOWPLACEMENT* lpwndpl)
- {
- ASSERT(::IsWindow(m_hWnd));
- ((WINDOWPLACEMENT*)lpwndpl)->length = sizeof(WINDOWPLACEMENT);
- return ::SetWindowPlacement(m_hWnd, lpwndpl);
- }
- /////////////////////////////////////////////////////////////////////////////
- // CWnd will delegate owner draw messages to self drawing controls
- // Drawing: for all 4 control types
- void CWnd::OnDrawItem(int /*nIDCtl*/, LPDRAWITEMSTRUCT lpDrawItemStruct)
- {
- if (lpDrawItemStruct->CtlType == ODT_MENU)
- {
- CMenu* pMenu = CMenu::FromHandlePermanent(
- (HMENU)lpDrawItemStruct->hwndItem);
- if (pMenu != NULL)
- {
- pMenu->DrawItem(lpDrawItemStruct);
- return; // eat it
- }
- }
- else
- {
- // reflect notification to child window control
- if (ReflectLastMsg(lpDrawItemStruct->hwndItem))
- return; // eat it
- }
- // not handled - do default
- Default();
- }
- // Drawing: for all 4 control types
- int CWnd::OnCompareItem(int /*nIDCtl*/, LPCOMPAREITEMSTRUCT lpCompareItemStruct)
- {
- // reflect notification to child window control
- LRESULT lResult;
- if (ReflectLastMsg(lpCompareItemStruct->hwndItem, &lResult))
- return (int)lResult; // eat it
- // not handled - do default
- return (int)Default();
- }
- void CWnd::OnDeleteItem(int /*nIDCtl*/, LPDELETEITEMSTRUCT lpDeleteItemStruct)
- {
- // reflect notification to child window control
- if (ReflectLastMsg(lpDeleteItemStruct->hwndItem))
- return; // eat it
- // not handled - do default
- Default();
- }
- int CWnd::OnCharToItem(UINT, CListBox* pWnd, UINT)
- {
- if (pWnd != NULL)
- {
- LRESULT lResult;
- if (pWnd->SendChildNotifyLastMsg(&lResult))
- return (int)lResult; // eat it
- }
- // not handled - do default
- return (int)Default();
- }
- int CWnd::OnVKeyToItem(UINT, CListBox* pWnd, UINT)
- {
- if (pWnd != NULL)
- {
- LRESULT lResult;
- if (pWnd->SendChildNotifyLastMsg(&lResult))
- return (int)lResult; // eat it
- }
- // not handled - do default
- return (int)Default();
- }
- /////////////////////////////////////////////////////////////////////////////
- // Self drawing menus are a little trickier
- BOOL CMenu::TrackPopupMenu(UINT nFlags, int x, int y,
- CWnd* pWnd, LPCRECT lpRect)
- {
- ASSERT(m_hMenu != NULL);
- _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
- HWND hWndOld = pThreadState->m_hTrackingWindow;
- HMENU hMenuOld = pThreadState->m_hTrackingMenu;
- pThreadState->m_hTrackingWindow = pWnd->GetSafeHwnd();
- pThreadState->m_hTrackingMenu = m_hMenu;
- BOOL bOK = ::TrackPopupMenu(m_hMenu, nFlags, x, y, 0,
- pThreadState->m_hTrackingWindow, lpRect);
- pThreadState->m_hTrackingWindow = hWndOld;
- pThreadState->m_hTrackingMenu = hMenuOld;
- return bOK;
- }
- AFX_STATIC CMenu* AFXAPI _AfxFindPopupMenuFromID(CMenu* pMenu, UINT nID)
- {
- ASSERT_VALID(pMenu);
- // walk through all items, looking for ID match
- UINT nItems = pMenu->GetMenuItemCount();
- for (int iItem = 0; iItem < (int)nItems; iItem++)
- {
- CMenu* pPopup = pMenu->GetSubMenu(iItem);
- if (pPopup != NULL)
- {
- // recurse to child popup
- pPopup = _AfxFindPopupMenuFromID(pPopup, nID);
- // check popups on this popup
- if (pPopup != NULL)
- return pPopup;
- }
- else if (pMenu->GetMenuItemID(iItem) == nID)
- {
- // it is a normal item inside our popup
- pMenu = CMenu::FromHandlePermanent(pMenu->m_hMenu);
- return pMenu;
- }
- }
- // not found
- return NULL;
- }
- // Measure item implementation relies on unique control/menu IDs
- void CWnd::OnMeasureItem(int /*nIDCtl*/, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
- {
- if (lpMeasureItemStruct->CtlType == ODT_MENU)
- {
- ASSERT(lpMeasureItemStruct->CtlID == 0);
- CMenu* pMenu;
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- if (pThreadState->m_hTrackingWindow == m_hWnd)
- {
- // start from popup
- pMenu = CMenu::FromHandle(pThreadState->m_hTrackingMenu);
- }
- else
- {
- // start from menubar
- pMenu = GetMenu();
- }
- pMenu = _AfxFindPopupMenuFromID(pMenu, lpMeasureItemStruct->itemID);
- if (pMenu != NULL)
- pMenu->MeasureItem(lpMeasureItemStruct);
- else
- TRACE1("Warning: unknown WM_MEASUREITEM for menu item 0x%04X.\n",
- lpMeasureItemStruct->itemID);
- }
- else
- {
- CWnd* pChild = GetDescendantWindow(lpMeasureItemStruct->CtlID, TRUE);
- if (pChild != NULL && pChild->SendChildNotifyLastMsg())
- return; // eaten by child
- }
- // not handled - do default
- Default();
- }
- /////////////////////////////////////////////////////////////////////////////
- // Additional helpers for WNDCLASS init
- // like RegisterClass, except will automatically call UnregisterClass
- BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass)
- {
- WNDCLASS wndcls;
- if (GetClassInfo(lpWndClass->hInstance, lpWndClass->lpszClassName,
- &wndcls))
- {
- // class already registered
- return TRUE;
- }
- if (!::RegisterClass(lpWndClass))
- {
- TRACE1("Can't register window class named %s\n",
- lpWndClass->lpszClassName);
- return FALSE;
- }
- if (afxContextIsDLL)
- {
- AfxLockGlobals(CRIT_REGCLASSLIST);
- TRY
- {
- // class registered successfully, add to registered list
- AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
- LPTSTR lpszUnregisterList = pModuleState->m_szUnregisterList;
- // the buffer is of fixed size -- ensure that it does not overflow
- ASSERT(lstrlen(lpszUnregisterList) + 1 +
- lstrlen(lpWndClass->lpszClassName) + 1 <
- _countof(pModuleState->m_szUnregisterList));
- // append classname + newline to m_szUnregisterList
- lstrcat(lpszUnregisterList, lpWndClass->lpszClassName);
- TCHAR szTemp[2];
- szTemp[0] = '\n';
- szTemp[1] = '\0';
- lstrcat(lpszUnregisterList, szTemp);
- }
- CATCH_ALL(e)
- {
- AfxUnlockGlobals(CRIT_REGCLASSLIST);
- THROW_LAST();
- // Note: DELETE_EXCEPTION not required.
- }
- END_CATCH_ALL
- AfxUnlockGlobals(CRIT_REGCLASSLIST);
- }
- return TRUE;
- }
- LPCTSTR AFXAPI AfxRegisterWndClass(UINT nClassStyle,
- HCURSOR hCursor, HBRUSH hbrBackground, HICON hIcon)
- {
- // Returns a temporary string name for the class
- // Save in a CString if you want to use it for a long time
- LPTSTR lpszName = AfxGetThreadState()->m_szTempClassName;
- // generate a synthetic name for this class
- HINSTANCE hInst = AfxGetInstanceHandle();
- if (hCursor == NULL && hbrBackground == NULL && hIcon == NULL)
- wsprintf(lpszName, _T("Afx:%x:%x"), (UINT)hInst, nClassStyle);
- else
- wsprintf(lpszName, _T("Afx:%x:%x:%x:%x:%x"), (UINT)hInst, nClassStyle,
- (UINT)hCursor, (UINT)hbrBackground, (UINT)hIcon);
- // see if the class already exists
- WNDCLASS wndcls;
- if (::GetClassInfo(hInst, lpszName, &wndcls))
- {
- // already registered, assert everything is good
- ASSERT(wndcls.style == nClassStyle);
- // NOTE: We have to trust that the hIcon, hbrBackground, and the
- // hCursor are semantically the same, because sometimes Windows does
- // some internal translation or copying of those handles before
- // storing them in the internal WNDCLASS retrieved by GetClassInfo.
- return lpszName;
- }
- // otherwise we need to register a new class
- wndcls.style = nClassStyle;
- wndcls.lpfnWndProc = DefWindowProc;
- wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
- wndcls.hInstance = hInst;
- wndcls.hIcon = hIcon;
- wndcls.hCursor = hCursor;
- wndcls.hbrBackground = hbrBackground;
- wndcls.lpszMenuName = NULL;
- wndcls.lpszClassName = lpszName;
- if (!AfxRegisterClass(&wndcls))
- AfxThrowResourceException();
- // return thread-local pointer
- return lpszName;
- }
- struct AFX_CTLCOLOR
- {
- HWND hWnd;
- HDC hDC;
- UINT nCtlType;
- };
- LRESULT CWnd::OnNTCtlColor(WPARAM wParam, LPARAM lParam)
- {
- // fill in special struct for compatiblity with 16-bit WM_CTLCOLOR
- AFX_CTLCOLOR ctl;
- ctl.hDC = (HDC)wParam;
- ctl.hWnd = (HWND)lParam;
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- ctl.nCtlType = pThreadState->m_lastSentMsg.message - WM_CTLCOLORMSGBOX;
- ASSERT(ctl.nCtlType >= CTLCOLOR_MSGBOX);
- ASSERT(ctl.nCtlType <= CTLCOLOR_STATIC);
- // Note: We call the virtual WindowProc for this window directly,
- // instead of calling AfxCallWindowProc, so that Default()
- // will still work (it will call the Default window proc with
- // the original Win32 WM_CTLCOLOR message).
- return WindowProc(WM_CTLCOLOR, 0, (LPARAM)&ctl);
- }
- /////////////////////////////////////////////////////////////////////////////
- // CWnd extensions for help support
- void CWnd::WinHelp(DWORD dwData, UINT nCmd)
- {
- CWinApp* pApp = AfxGetApp();
- ASSERT_VALID(pApp);
- ASSERT(pApp->m_pszHelpFilePath != NULL);
- CWaitCursor wait;
- if (IsFrameWnd())
- {
- // CFrameWnd windows should be allowed to exit help mode first
- CFrameWnd* pFrameWnd = (CFrameWnd*)this;
- pFrameWnd->ExitHelpMode();
- }
- // cancel any tracking modes
- SendMessage(WM_CANCELMODE);
- SendMessageToDescendants(WM_CANCELMODE, 0, 0, TRUE, TRUE);
- // need to use top level parent (for the case where m_hWnd is in DLL)
- CWnd* pWnd = GetTopLevelParent();
- pWnd->SendMessage(WM_CANCELMODE);
- pWnd->SendMessageToDescendants(WM_CANCELMODE, 0, 0, TRUE, TRUE);
- // attempt to cancel capture
- HWND hWndCapture = ::GetCapture();
- if (hWndCapture != NULL)
- ::SendMessage(hWndCapture, WM_CANCELMODE, 0, 0);
- TRACE3("WinHelp: pszHelpFile = '%s', dwData: $%lx, fuCommand: %d.\n",
- pApp->m_pszHelpFilePath, dwData, nCmd);
- // finally, run the Windows Help engine
- if (!::WinHelp(pWnd->m_hWnd, pApp->m_pszHelpFilePath, nCmd, dwData))
- AfxMessageBox(AFX_IDP_FAILED_TO_LAUNCH_HELP);
- }
- /////////////////////////////////////////////////////////////////////////////
- // Message table implementation
- BEGIN_MESSAGE_MAP(CWnd, CCmdTarget)
- ON_MESSAGE(WM_CTLCOLORSTATIC, OnNTCtlColor)
- ON_MESSAGE(WM_CTLCOLOREDIT, OnNTCtlColor)
- ON_MESSAGE(WM_CTLCOLORBTN, OnNTCtlColor)
- ON_MESSAGE(WM_CTLCOLORLISTBOX, OnNTCtlColor)
- ON_MESSAGE(WM_CTLCOLORDLG, OnNTCtlColor)
- ON_MESSAGE(WM_CTLCOLORMSGBOX, OnNTCtlColor)
- ON_MESSAGE(WM_CTLCOLORSCROLLBAR, OnNTCtlColor)
- //{{AFX_MSG_MAP(CWnd)
- ON_WM_DRAWITEM()
- ON_WM_MEASUREITEM()
- ON_WM_CTLCOLOR()
- ON_WM_COMPAREITEM()
- ON_WM_ENTERIDLE()
- ON_WM_HSCROLL()
- ON_WM_VSCROLL()
- ON_WM_DELETEITEM()
- ON_WM_CHARTOITEM()
- ON_WM_VKEYTOITEM()
- ON_WM_NCDESTROY()
- ON_WM_PARENTNOTIFY()
- ON_WM_SYSCOLORCHANGE()
- ON_WM_DEVMODECHANGE()
- ON_WM_HELPINFO()
- ON_WM_SETTINGCHANGE()
- //}}AFX_MSG_MAP
- #ifndef _AFX_NO_OCC_SUPPORT
- ON_WM_DESTROY()
- #endif
- ON_MESSAGE(WM_ACTIVATETOPLEVEL, OnActivateTopLevel)
- ON_MESSAGE(WM_DISPLAYCHANGE, OnDisplayChange)
- ON_REGISTERED_MESSAGE(CWnd::m_nMsgDragList, OnDragList)
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // Routines for fast search of message maps
- const AFX_MSGMAP_ENTRY* AFXAPI
- AfxFindMessageEntry(const AFX_MSGMAP_ENTRY* lpEntry,
- UINT nMsg, UINT nCode, UINT nID)
- {
- #if defined(_M_IX86) && !defined(_AFX_PORTABLE)
- // 32-bit Intel 386/486 version.
- ASSERT(offsetof(AFX_MSGMAP_ENTRY, nMessage) == 0);
- ASSERT(offsetof(AFX_MSGMAP_ENTRY, nCode) == 4);
- ASSERT(offsetof(AFX_MSGMAP_ENTRY, nID) == 8);
- ASSERT(offsetof(AFX_MSGMAP_ENTRY, nLastID) == 12);
- ASSERT(offsetof(AFX_MSGMAP_ENTRY, nSig) == 16);
- _asm
- {
- MOV EBX,lpEntry
- MOV EAX,nMsg
- MOV EDX,nCode
- MOV ECX,nID
- __loop:
- CMP DWORD PTR [EBX+16],0 ; nSig (0 => end)
- JZ __failed
- CMP EAX,DWORD PTR [EBX] ; nMessage
- JE __found_message
- __next:
- ADD EBX,SIZE AFX_MSGMAP_ENTRY
- JMP short __loop
- __found_message:
- CMP EDX,DWORD PTR [EBX+4] ; nCode
- JNE __next
- // message and code good so far
- // check the ID
- CMP ECX,DWORD PTR [EBX+8] ; nID
- JB __next
- CMP ECX,DWORD PTR [EBX+12] ; nLastID
- JA __next
- // found a match
- MOV lpEntry,EBX ; return EBX
- JMP short __end
- __failed:
- XOR EAX,EAX ; return NULL
- MOV lpEntry,EAX
- __end:
- }
- return lpEntry;
- #else // _AFX_PORTABLE
- // C version of search routine
- while (lpEntry->nSig != AfxSig_end)
- {
- if (lpEntry->nMessage == nMsg && lpEntry->nCode == nCode &&
- nID >= lpEntry->nID && nID <= lpEntry->nLastID)
- {
- return lpEntry;
- }
- lpEntry++;
- }
- return NULL; // not found
- #endif // _AFX_PORTABLE
- }
- /////////////////////////////////////////////////////////////////////////////
- // Cache of most recently sent messages
- #ifndef iHashMax
- // iHashMax must be a power of two
- #define iHashMax 512
- #endif
- struct AFX_MSG_CACHE
- {
- UINT nMsg;
- const AFX_MSGMAP_ENTRY* lpEntry;
- const AFX_MSGMAP* pMessageMap;
- };
- AFX_MSG_CACHE _afxMsgCache[iHashMax];
- void AFXAPI AfxResetMsgCache()
- {
- memset(_afxMsgCache, 0, sizeof(_afxMsgCache));
- }
- /////////////////////////////////////////////////////////////////////////////
- // main WindowProc implementation
- LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
- {
- // OnWndMsg does most of the work, except for DefWindowProc call
- LRESULT lResult = 0;
- if (!OnWndMsg(message, wParam, lParam, &lResult))
- lResult = DefWindowProc(message, wParam, lParam);
- return lResult;
- }
- BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
- {
- LRESULT lResult = 0;
- // special case for commands
- if (message == WM_COMMAND)
- {
- if (OnCommand(wParam, lParam))
- {
- lResult = 1;
- goto LReturnTrue;
- }
- return FALSE;
- }
- // special case for notifies
- if (message == WM_NOTIFY)
- {
- NMHDR* pNMHDR = (NMHDR*)lParam;
- if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))
- goto LReturnTrue;
- return FALSE;
- }
- // special case for activation
- if (message == WM_ACTIVATE)
- _AfxHandleActivate(this, wParam, CWnd::FromHandle((HWND)lParam));
- // special case for set cursor HTERROR
- if (message == WM_SETCURSOR &&
- _AfxHandleSetCursor(this, (short)LOWORD(lParam), HIWORD(lParam)))
- {
- lResult = 1;
- goto LReturnTrue;
- }
- const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap();
- UINT iHash; iHash = (LOWORD((DWORD)pMessageMap) ^ message) & (iHashMax-1);
- AfxLockGlobals(CRIT_WINMSGCACHE);
- AFX_MSG_CACHE* pMsgCache; pMsgCache = &_afxMsgCache[iHash];
- const AFX_MSGMAP_ENTRY* lpEntry;
- if (message == pMsgCache->nMsg && pMessageMap == pMsgCache->pMessageMap)
- {
- // cache hit
- lpEntry = pMsgCache->lpEntry;
- AfxUnlockGlobals(CRIT_WINMSGCACHE);
- if (lpEntry == NULL)
- return FALSE;
- // cache hit, and it needs to be handled
- if (message < 0xC000)
- goto LDispatch;
- else
- goto LDispatchRegistered;
- }
- else
- {
- // not in cache, look for it
- pMsgCache->nMsg = message;
- pMsgCache->pMessageMap = pMessageMap;
- #ifdef _AFXDLL
- for (/* pMessageMap already init'ed */; pMessageMap != NULL;
- pMessageMap = (*pMessageMap->pfnGetBaseMap)())
- #else
- for (/* pMessageMap already init'ed */; pMessageMap != NULL;
- pMessageMap = pMessageMap->pBaseMap)
- #endif
- {
- // Note: catch not so common but fatal mistake!!
- // BEGIN_MESSAGE_MAP(CMyWnd, CMyWnd)
- #ifdef _AFXDLL
- ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)());
- #else
- ASSERT(pMessageMap != pMessageMap->pBaseMap);
- #endif
- if (message < 0xC000)
- {
- // constant window message
- if ((lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries,
- message, 0, 0)) != NULL)
- {
- pMsgCache->lpEntry = lpEntry;
- AfxUnlockGlobals(CRIT_WINMSGCACHE);
- goto LDispatch;
- }
- }
- else
- {
- // registered windows message
- lpEntry = pMessageMap->lpEntries;
- while ((lpEntry = AfxFindMessageEntry(lpEntry, 0xC000, 0, 0)) != NULL)
- {
- UINT* pnID = (UINT*)(lpEntry->nSig);
- ASSERT(*pnID >= 0xC000 || *pnID == 0);
- // must be successfully registered
- if (*pnID == message)
- {
- pMsgCache->lpEntry = lpEntry;
- AfxUnlockGlobals(CRIT_WINMSGCACHE);
- goto LDispatchRegistered;
- }
- lpEntry++; // keep looking past this one
- }
- }
- }
- pMsgCache->lpEntry = NULL;
- AfxUnlockGlobals(CRIT_WINMSGCACHE);
- return FALSE;
- }
- ASSERT(FALSE); // not reached
- LDispatch:
- ASSERT(message < 0xC000);
- union MessageMapFunctions mmf;
- mmf.pfn = lpEntry->pfn;
- // if we've got WM_SETTINGCHANGE / WM_WININICHANGE, we need to
- // decide if we're going to call OnWinIniChange() or OnSettingChange()
- int nSig;
- nSig = lpEntry->nSig;
- if (lpEntry->nID == WM_SETTINGCHANGE)
- {
- DWORD dwVersion = GetVersion();
- if (LOBYTE(LOWORD(dwVersion)) >= 4)
- nSig = AfxSig_vws;
- else
- nSig = AfxSig_vs;
- }
- switch (nSig)
- {
- default:
- ASSERT(FALSE);
- break;
- case AfxSig_bD:
- lResult = (this->*mmf.pfn_bD)(CDC::FromHandle((HDC)wParam));
- break;
- case AfxSig_bb: // AfxSig_bb, AfxSig_bw, AfxSig_bh
- lResult = (this->*mmf.pfn_bb)((BOOL)wParam);
- break;
- case AfxSig_bWww: // really AfxSig_bWiw
- lResult = (this->*mmf.pfn_bWww)(CWnd::FromHandle((HWND)wParam),
- (short)LOWORD(lParam), HIWORD(lParam));
- break;
- case AfxSig_bWCDS:
- lResult = (this->*mmf.pfn_bWCDS)(CWnd::FromHandle((HWND)wParam),
- (COPYDATASTRUCT*)lParam);
- break;
- case AfxSig_bHELPINFO:
- lResult = (this->*mmf.pfn_bHELPINFO)((HELPINFO*)lParam);
- break;
- case AfxSig_hDWw:
- {
- // special case for OnCtlColor to avoid too many temporary objects
- ASSERT(message == WM_CTLCOLOR);
- AFX_CTLCOLOR* pCtl = (AFX_CTLCOLOR*)lParam;
- CDC dcTemp; dcTemp.m_hDC = pCtl->hDC;
- CWnd wndTemp; wndTemp.m_hWnd = pCtl->hWnd;
- UINT nCtlType = pCtl->nCtlType;
- // if not coming from a permanent window, use stack temporary
- CWnd* pWnd = CWnd::FromHandlePermanent(wndTemp.m_hWnd);
- if (pWnd == NULL)
- {
- #ifndef _AFX_NO_OCC_SUPPORT
- // determine the site of the OLE control if it is one
- COleControlSite* pSite;
- if (m_pCtrlCont != NULL && (pSite = (COleControlSite*)
- m_pCtrlCont->m_siteMap.GetValueAt(wndTemp.m_hWnd)) != NULL)
- {
- wndTemp.m_pCtrlSite = pSite;
- }
- #endif
- pWnd = &wndTemp;
- }
- HBRUSH hbr = (this->*mmf.pfn_hDWw)(&dcTemp, pWnd, nCtlType);
- // fast detach of temporary objects
- dcTemp.m_hDC = NULL;
- wndTemp.m_hWnd = NULL;
- lResult = (LRESULT)hbr;
- }
- break;
- case AfxSig_hDw:
- {
- // special case for CtlColor to avoid too many temporary objects
- ASSERT(message == WM_REFLECT_BASE+WM_CTLCOLOR);
- AFX_CTLCOLOR* pCtl = (AFX_CTLCOLOR*)lParam;
- CDC dcTemp; dcTemp.m_hDC = pCtl->hDC;
- UINT nCtlType = pCtl->nCtlType;
- HBRUSH hbr = (this->*mmf.pfn_hDw)(&dcTemp, nCtlType);
- // fast detach of temporary objects
- dcTemp.m_hDC = NULL;
- lResult = (LRESULT)hbr;
- }
- break;
- case AfxSig_iwWw:
- lResult = (this->*mmf.pfn_iwWw)(LOWORD(wParam),
- CWnd::FromHandle((HWND)lParam), HIWORD(wParam));
- break;
- case AfxSig_iww:
- lResult = (this->*mmf.pfn_iww)(LOWORD(wParam), HIWORD(wParam));
- break;
- case AfxSig_iWww: // really AfxSig_iWiw
- lResult = (this->*mmf.pfn_iWww)(CWnd::FromHandle((HWND)wParam),
- (short)LOWORD(lParam), HIWORD(lParam));
- break;
- case AfxSig_is:
- lResult = (this->*mmf.pfn_is)((LPTSTR)lParam);
- break;
- case AfxSig_lwl:
- lResult = (this->*mmf.pfn_lwl)(wParam, lParam);
- break;
- case AfxSig_lwwM:
- lResult = (this->*mmf.pfn_lwwM)((UINT)LOWORD(wParam),
- (UINT)HIWORD(wParam), (CMenu*)CMenu::FromHandle((HMENU)lParam));
- break;
- case AfxSig_vv:
- (this->*mmf.pfn_vv)();
- break;
- case AfxSig_vw: // AfxSig_vb, AfxSig_vh
- (this->*mmf.pfn_vw)(wParam);
- break;
- case AfxSig_vww:
- (this->*mmf.pfn_vww)((UINT)wParam, (UINT)lParam);
- break;
- case AfxSig_vvii:
- (this->*mmf.pfn_vvii)((short)LOWORD(lParam), (short)HIWORD(lParam));
- break;
- case AfxSig_vwww:
- (this->*mmf.pfn_vwww)(wParam, LOWORD(lParam), HIWORD(lParam));
- break;
- case AfxSig_vwii:
- (this->*mmf.pfn_vwii)(wParam, LOWORD(lParam), HIWORD(lParam));
- break;
- case AfxSig_vwl:
- (this->*mmf.pfn_vwl)(wParam, lParam);
- break;
- case AfxSig_vbWW:
- (this->*mmf.pfn_vbWW)(m_hWnd == (HWND)lParam,
- CWnd::FromHandle((HWND)lParam),
- CWnd::FromHandle((HWND)wParam));
- break;
- case AfxSig_vD:
- (this->*mmf.pfn_vD)(CDC::FromHandle((HDC)wParam));
- break;
- case AfxSig_vM:
- (this->*mmf.pfn_vM)(CMenu::FromHandle((HMENU)wParam));
- break;
- case AfxSig_vMwb:
- (this->*mmf.pfn_vMwb)(CMenu::FromHandle((HMENU)wParam),
- LOWORD(lParam), (BOOL)HIWORD(lParam));
- break;
- case AfxSig_vW:
- (this->*mmf.pfn_vW)(CWnd::FromHandle((HWND)wParam));
- break;
- case AfxSig_vW2:
- (this->*mmf.pfn_vW)(CWnd::FromHandle((HWND)lParam));
- break;
- case AfxSig_vWww:
- (this->*mmf.pfn_vWww)(CWnd::FromHandle((HWND)wParam), LOWORD(lParam),
- HIWORD(lParam));
- break;
- case AfxSig_vWp:
- {
- CPoint point((DWORD)lParam);
- (this->*mmf.pfn_vWp)(CWnd::FromHandle((HWND)wParam), point);
- }
- break;
- case AfxSig_vWh:
- (this->*mmf.pfn_vWh)(CWnd::FromHandle((HWND)wParam),
- (HANDLE)lParam);
- break;
- case AfxSig_vwW:
- (this->*mmf.pfn_vwW)(wParam, CWnd::FromHandle((HWND)lParam));
- break;
- case AfxSig_vwWb:
- (this->*mmf.pfn_vwWb)((UINT)(LOWORD(wParam)),
- CWnd::FromHandle((HWND)lParam), (BOOL)HIWORD(wParam));
- break;
- case AfxSig_vwwW:
- case AfxSig_vwwx:
- {
- // special case for WM_VSCROLL and WM_HSCROLL
- ASSERT(message == WM_VSCROLL || message == WM_HSCROLL ||
- message == WM_VSCROLL+WM_REFLECT_BASE || message == WM_HSCROLL+WM_REFLECT_BASE);
- int nScrollCode = (short)LOWORD(wParam);
- int nPos = (short)HIWORD(wParam);
- if (lpEntry->nSig == AfxSig_vwwW)
- (this->*mmf.pfn_vwwW)(nScrollCode, nPos,
- CWnd::FromHandle((HWND)lParam));
- else
- (this->*mmf.pfn_vwwx)(nScrollCode, nPos);
- }
- break;
- case AfxSig_vs:
- (this->*mmf.pfn_vs)((LPTSTR)lParam);
- break;
- case AfxSig_vws:
- (this->*mmf.pfn_vws)((UINT) wParam, (LPCTSTR)lParam);
- break;
- case AfxSig_vOWNER:
- (this->*mmf.pfn_vOWNER)((int)wParam, (LPTSTR)lParam);
- lResult = TRUE;
- break;
- case AfxSig_iis:
- lResult = (this->*mmf.pfn_iis)((int)wParam, (LPTSTR)lParam);
- break;
- case AfxSig_wp:
- {
- CPoint point((DWORD)lParam);
- lResult = (this->*mmf.pfn_wp)(point);
- }
- break;
- case AfxSig_wv: // AfxSig_bv, AfxSig_wv
- lResult = (this->*mmf.pfn_wv)();
- break;
- case AfxSig_vCALC:
- (this->*mmf.pfn_vCALC)((BOOL)wParam, (NCCALCSIZE_PARAMS*)lParam);
- break;
- case AfxSig_vPOS:
- (this->*mmf.pfn_vPOS)((WINDOWPOS*)lParam);
- break;
- case AfxSig_vwwh:
- (this->*mmf.pfn_vwwh)(LOWORD(wParam), HIWORD(wParam), (HANDLE)lParam);
- break;
- case AfxSig_vwp:
- {
- CPoint point((DWORD)lParam);
- (this->*mmf.pfn_vwp)(wParam, point);
- break;
- }
- case AfxSig_vwSIZING:
- (this->*mmf.pfn_vwl)(wParam, lParam);
- lResult = TRUE;
- break;
- case AfxSig_bwsp:
- lResult = (this->*mmf.pfn_bwsp)(LOWORD(wParam), (short) HIWORD(wParam),
- CPoint(LOWORD(lParam), HIWORD(lParam)));
- if (!lResult)
- return FALSE;
- }
- goto LReturnTrue;
- LDispatchRegistered: // for registered windows messages
- ASSERT(message >= 0xC000);
- mmf.pfn = lpEntry->pfn;
- lResult = (this->*mmf.pfn_lwl)(wParam, lParam);
- LReturnTrue:
- if (pResult != NULL)
- *pResult = lResult;
- return TRUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CTestCmdUI - used to test for disabled commands before dispatching
- class CTestCmdUI : public CCmdUI
- {
- public:
- CTestCmdUI();
- public: // re-implementations only
- virtual void Enable(BOOL bOn);
- virtual void SetCheck(int nCheck);
- virtual void SetRadio(BOOL bOn);
- virtual void SetText(LPCTSTR);
- BOOL m_bEnabled;
- };
- CTestCmdUI::CTestCmdUI()
- {
- m_bEnabled = TRUE; // assume it is enabled
- }
- void CTestCmdUI::Enable(BOOL bOn)
- {
- m_bEnabled = bOn;
- m_bEnableChanged = TRUE;
- }
- void CTestCmdUI::SetCheck(int)
- {
- // do nothing -- just want to know about calls to Enable
- }
- void CTestCmdUI::SetRadio(BOOL)
- {
- // do nothing -- just want to know about calls to Enable
- }
- void CTestCmdUI::SetText(LPCTSTR)
- {
- // do nothing -- just want to know about calls to Enable
- }
- /////////////////////////////////////////////////////////////////////////////
- // CWnd command handling
- BOOL CWnd::OnCommand(WPARAM wParam, LPARAM lParam)
- // return TRUE if command invocation was attempted
- {
- UINT nID = LOWORD(wParam);
- HWND hWndCtrl = (HWND)lParam;
- int nCode = HIWORD(wParam);
- // default routing for command messages (through closure table)
- if (hWndCtrl == NULL)
- {
- // zero IDs for normal commands are not allowed
- if (nID == 0)
- return FALSE;
- // make sure command has not become disabled before routing
- CTestCmdUI state;
- state.m_nID = nID;
- OnCmdMsg(nID, CN_UPDATE_COMMAND_UI, &state, NULL);
- if (!state.m_bEnabled)
- {
- TRACE1("Warning: not executing disabled command %d\n", nID);
- return TRUE;
- }
- // menu or accelerator
- nCode = CN_COMMAND;
- }
- else
- {
- // control notification
- ASSERT(nID == 0 || ::IsWindow(hWndCtrl));
- if (_afxThreadState->m_hLockoutNotifyWindow == m_hWnd)
- return TRUE; // locked out - ignore control notification
- // reflect notification to child window control
- if (ReflectLastMsg(hWndCtrl))
- return TRUE; // eaten by child
- // zero IDs for normal commands are not allowed
- if (nID == 0)
- return FALSE;
- }
- #ifdef _DEBUG
- if (nCode < 0 && nCode != (int)0x8000)
- TRACE1("Implementation Warning: control notification = $%X.\n",
- nCode);
- #endif
- return OnCmdMsg(nID, nCode, NULL, NULL);
- }
- BOOL CWnd::OnNotify(WPARAM, LPARAM lParam, LRESULT* pResult)
- {
- ASSERT(pResult != NULL);
- NMHDR* pNMHDR = (NMHDR*)lParam;
- HWND hWndCtrl = pNMHDR->hwndFrom;
- // get the child ID from the window itself
- UINT nID = _AfxGetDlgCtrlID(hWndCtrl);
- int nCode = pNMHDR->code;
- ASSERT(hWndCtrl != NULL);
- ASSERT(::IsWindow(hWndCtrl));
- if (_afxThreadState->m_hLockoutNotifyWindow == m_hWnd)
- return TRUE; // locked out - ignore control notification
- // reflect notification to child window control
- if (ReflectLastMsg(hWndCtrl, pResult))
- return TRUE; // eaten by child
- AFX_NOTIFY notify;
- notify.pResult = pResult;
- notify.pNMHDR = pNMHDR;
- return OnCmdMsg(nID, MAKELONG(nCode, WM_NOTIFY), ¬ify, NULL);
- }
- /////////////////////////////////////////////////////////////////////////////
- // CWnd extensions
- CFrameWnd* CWnd::GetParentFrame() const
- {
- if (GetSafeHwnd() == NULL) // no Window attached
- return NULL;
- ASSERT_VALID(this);
- CWnd* pParentWnd = GetParent(); // start with one parent up
- while (pParentWnd != NULL)
- {
- if (pParentWnd->IsFrameWnd())
- return (CFrameWnd*)pParentWnd;
- pParentWnd = pParentWnd->GetParent();
- }
- return NULL;
- }
- HWND AFXAPI AfxGetParentOwner(HWND hWnd)
- {
- // check for permanent-owned window first
- CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
- if (pWnd != NULL)
- return pWnd->GetOwner()->GetSafeHwnd();
- // otherwise, return parent in the Windows sense
- return (::GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) ?
- ::GetParent(hWnd) : ::GetWindow(hWnd, GW_OWNER);
- }
- CWnd* CWnd::GetTopLevelParent() const
- {
- if (GetSafeHwnd() == NULL) // no Window attached
- return NULL;
- ASSERT_VALID(this);
- HWND hWndParent = m_hWnd;
- HWND hWndT;
- while ((hWndT = AfxGetParentOwner(hWndParent)) != NULL)
- hWndParent = hWndT;
- return CWnd::FromHandle(hWndParent);
- }
- CWnd* CWnd::GetTopLevelOwner() const
- {
- if (GetSafeHwnd() == NULL) // no Window attached
- return NULL;
- ASSERT_VALID(this);
- HWND hWndOwner = m_hWnd;
- HWND hWndT;
- while ((hWndT = ::GetWindow(hWndOwner, GW_OWNER)) != NULL)
- hWndOwner = hWndT;
- return CWnd::FromHandle(hWndOwner);
- }
- CWnd* CWnd::GetParentOwner() const
- {
- if (GetSafeHwnd() == NULL) // no Window attached
- return NULL;
- ASSERT_VALID(this);
- HWND hWndParent = m_hWnd;
- HWND hWndT;
- while ((::GetWindowLong(hWndParent, GWL_STYLE) & WS_CHILD) &&
- (hWndT = ::GetParent(hWndParent)) != NULL)
- {
- hWndParent = hWndT;
- }
- return CWnd::FromHandle(hWndParent);
- }
- BOOL CWnd::IsTopParentActive() const
- {
- ASSERT(m_hWnd != NULL);
- ASSERT_VALID(this);
- return CWnd::GetForegroundWindow() ==
- GetTopLevelParent()->GetLastActivePopup();
- }
- void CWnd::ActivateTopParent()
- {
- // special activate logic for floating toolbars and palettes
- CWnd* pTopLevel = GetTopLevelParent();
- CWnd* pActiveWnd = GetForegroundWindow();
- if (pActiveWnd == NULL ||
- !(pActiveWnd->m_hWnd == m_hWnd || ::IsChild(pActiveWnd->m_hWnd, m_hWnd)))
- {
- // clicking on floating frame when it does not have
- // focus itself -- activate the toplevel frame instead.
- pTopLevel->SetForegroundWindow();
- }
- }
- CFrameWnd* CWnd::GetTopLevelFrame() const
- {
- if (GetSafeHwnd() == NULL) // no Window attached
- return NULL;
- ASSERT_VALID(this);
- CFrameWnd* pFrameWnd = (CFrameWnd*)this;
- if (!IsFrameWnd())
- pFrameWnd = GetParentFrame();
- if (pFrameWnd != NULL)
- {
- CFrameWnd* pTemp;
- while ((pTemp = pFrameWnd->GetParentFrame()) != NULL)
- pFrameWnd = pTemp;
- }
- return pFrameWnd;
- }
- CWnd* PASCAL CWnd::GetSafeOwner(CWnd* pParent, HWND* pWndTop)
- {
- HWND hWnd = GetSafeOwner_(pParent->GetSafeHwnd(), pWndTop);
- return CWnd::FromHandle(hWnd);
- }
- int CWnd::MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption, UINT nType)
- {
- if (lpszCaption == NULL)
- lpszCaption = AfxGetAppName();
- int nResult = ::MessageBox(GetSafeHwnd(), lpszText, lpszCaption, nType);
- return nResult;
- }
- CWnd* PASCAL CWnd::GetDescendantWindow(HWND hWnd, int nID, BOOL bOnlyPerm)
- {
- // GetDlgItem recursive (return first found)
- // breadth-first for 1 level, then depth-first for next level
- // use GetDlgItem since it is a fast USER function
- HWND hWndChild;
- CWnd* pWndChild;
- if ((hWndChild = ::GetDlgItem(hWnd, nID)) != NULL)
- {
- if (::GetTopWindow(hWndChild) != NULL)
- {
- // children with the same ID as their parent have priority
- pWndChild = GetDescendantWindow(hWndChild, nID, bOnlyPerm);
- if (pWndChild != NULL)
- return pWndChild;
- }
- // return temporary handle if allowed
- if (!bOnlyPerm)
- return CWnd::FromHandle(hWndChild);
- // return only permanent handle
- pWndChild = CWnd::FromHandlePermanent(hWndChild);
- if (pWndChild != NULL)
- return pWndChild;
- }
- // walk each child
- for (hWndChild = ::GetTopWindow(hWnd); hWndChild != NULL;
- hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
- {
- pWndChild = GetDescendantWindow(hWndChild, nID, bOnlyPerm);
- if (pWndChild != NULL)
- return pWndChild;
- }
- return NULL; // not found
- }
- void PASCAL CWnd::SendMessageToDescendants(HWND hWnd, UINT message,
- WPARAM wParam, LPARAM lParam, BOOL bDeep, BOOL bOnlyPerm)
- {
- // walk through HWNDs to avoid creating temporary CWnd objects
- // unless we need to call this function recursively
- for (HWND hWndChild = ::GetTopWindow(hWnd); hWndChild != NULL;
- hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
- {
- // if bOnlyPerm is TRUE, don't send to non-permanent windows
- if (bOnlyPerm)
- {
- CWnd* pWnd = CWnd::FromHandlePermanent(hWndChild);
- if (pWnd != NULL)
- {
- // call window proc directly since it is a C++ window
- AfxCallWndProc(pWnd, pWnd->m_hWnd, message, wParam, lParam);
- }
- }
- else
- {
- // send message with Windows SendMessage API
- ::SendMessage(hWndChild, message, wParam, lParam);
- }
- if (bDeep && ::GetTopWindow(hWndChild) != NULL)
- {
- // send to child windows after parent
- SendMessageToDescendants(hWndChild, message, wParam, lParam,
- bDeep, bOnlyPerm);
- }
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- // Scroll bar helpers
- // hook for CWnd functions
- // only works for derived class (eg: CView) that override 'GetScrollBarCtrl'
- // if the window doesn't have a _visible_ windows scrollbar - then
- // look for a sibling with the appropriate ID
- CScrollBar* CWnd::GetScrollBarCtrl(int) const
- {
- return NULL; // no special scrollers supported
- }
- int CWnd::SetScrollPos(int nBar, int nPos, BOOL bRedraw)
- {
- CScrollBar* pScrollBar;
- if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
- return pScrollBar->SetScrollPos(nPos, bRedraw);
- else
- return ::SetScrollPos(m_hWnd, nBar, nPos, bRedraw);
- }
- int CWnd::GetScrollPos(int nBar) const
- {
- CScrollBar* pScrollBar;
- if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
- return pScrollBar->GetScrollPos();
- else
- return ::GetScrollPos(m_hWnd, nBar);
- }
- void CWnd::SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw)
- {
- CScrollBar* pScrollBar;
- if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
- pScrollBar->SetScrollRange(nMinPos, nMaxPos, bRedraw);
- else
- ::SetScrollRange(m_hWnd, nBar, nMinPos, nMaxPos, bRedraw);
- }
- void CWnd::GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const
- {
- CScrollBar* pScrollBar;
- if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
- pScrollBar->GetScrollRange(lpMinPos, lpMaxPos);
- else
- ::GetScrollRange(m_hWnd, nBar, lpMinPos, lpMaxPos);
- }
- // Turn on/off non-control scrollbars
- // for WS_?SCROLL scrollbars - show/hide them
- // for control scrollbar - enable/disable them
- void CWnd::EnableScrollBarCtrl(int nBar, BOOL bEnable)
- {
- CScrollBar* pScrollBar;
- if (nBar == SB_BOTH)
- {
- EnableScrollBarCtrl(SB_HORZ, bEnable);
- EnableScrollBarCtrl(SB_VERT, bEnable);
- }
- else if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
- {
- // control scrollbar - enable or disable
- pScrollBar->EnableWindow(bEnable);
- }
- else
- {
- // WS_?SCROLL scrollbar - show or hide
- ShowScrollBar(nBar, bEnable);
- }
- }
- BOOL CWnd::SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw)
- {
- ASSERT(lpScrollInfo != NULL);
- if (afxData.nWinVer < 0x333)
- return FALSE;
- HWND hWnd = m_hWnd;
- CScrollBar* pScrollBar;
- if (nBar != SB_CTL && (pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
- {
- hWnd = pScrollBar->m_hWnd;
- nBar = SB_CTL;
- }
- lpScrollInfo->cbSize = sizeof(*lpScrollInfo);
- ::SetScrollInfo(hWnd, nBar, lpScrollInfo, bRedraw);
- return TRUE;
- }
- BOOL CWnd::GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, UINT nMask)
- {
- ASSERT(lpScrollInfo != NULL);
- if (afxData.nWinVer < 0x333)
- return FALSE;
- HWND hWnd = m_hWnd;
- CScrollBar* pScrollBar;
- if (nBar != SB_CTL && (pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
- {
- hWnd = pScrollBar->m_hWnd;
- nBar = SB_CTL;
- }
- lpScrollInfo->cbSize = sizeof(*lpScrollInfo);
- lpScrollInfo->fMask = nMask;
- return ::GetScrollInfo(hWnd, nBar, lpScrollInfo);
- }
- int CWnd::GetScrollLimit(int nBar)
- {
- int nMin, nMax;
- GetScrollRange(nBar, &nMin, &nMax);
- SCROLLINFO info;
- if (GetScrollInfo(nBar, &info, SIF_PAGE))
- {
- nMax -= __max(info.nPage-1,0);
- }
- return nMax;
- }
- void CWnd::ScrollWindow(int xAmount, int yAmount,
- LPCRECT lpRect, LPCRECT lpClipRect)
- {
- ASSERT(::IsWindow(m_hWnd));
- if (IsWindowVisible() || lpRect != NULL || lpClipRect != NULL)
- {
- // When visible, let Windows do the scrolling
- ::ScrollWindow(m_hWnd, xAmount, yAmount, lpRect, lpClipRect);
- }
- else
- {
- // Windows does not perform any scrolling if the window is
- // not visible. This leaves child windows unscrolled.
- // To account for this oversight, the child windows are moved
- // directly instead.
- HWND hWndChild = ::GetWindow(m_hWnd, GW_CHILD);
- if (hWndChild != NULL)
- {
- for (; hWndChild != NULL;
- hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
- {
- CRect rect;
- ::GetWindowRect(hWndChild, &rect);
- ScreenToClient(&rect);
- ::SetWindowPos(hWndChild, NULL,
- rect.left+xAmount, rect.top+yAmount, 0, 0,
- SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOZORDER);
- }
- }
- }
- #ifndef _AFX_NO_OCC_SUPPORT
- if ((m_pCtrlCont == NULL) || (lpRect != NULL))
- return;
- // the following code is for OLE control containers only
- m_pCtrlCont->ScrollChildren(xAmount, yAmount);
- #endif // !_AFX_NO_OCC_SUPPORT
- }
- /////////////////////////////////////////////////////////////////////////////
- // minimal layout support
- void CWnd::RepositionBars(UINT nIDFirst, UINT nIDLast, UINT nIDLeftOver,
- UINT nFlags, LPRECT lpRectParam, LPCRECT lpRectClient, BOOL bStretch)
- {
- ASSERT(nFlags == 0 || nFlags == reposQuery || nFlags == reposExtra);
- // walk kids in order, control bars get the resize notification
- // which allow them to shrink the client area
- // remaining size goes to the 'nIDLeftOver' pane
- // NOTE: nIDFirst->nIDLast are usually 0->0xffff
- AFX_SIZEPARENTPARAMS layout;
- HWND hWndLeftOver = NULL;
- layout.bStretch = bStretch;
- layout.sizeTotal.cx = layout.sizeTotal.cy = 0;
- if (lpRectClient != NULL)
- layout.rect = *lpRectClient; // starting rect comes from parameter
- else
- GetClientRect(&layout.rect); // starting rect comes from client rect
- if (nFlags != reposQuery)
- layout.hDWP = ::BeginDeferWindowPos(8); // reasonable guess
- else
- layout.hDWP = NULL; // not actually doing layout
- for (HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
- hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
- {
- UINT nIDC = _AfxGetDlgCtrlID(hWndChild);
- CWnd* pWnd = CWnd::FromHandlePermanent(hWndChild);
- if (nIDC == nIDLeftOver)
- hWndLeftOver = hWndChild;
- else if (nIDC >= nIDFirst && nIDC <= nIDLast && pWnd != NULL)
- ::SendMessage(hWndChild, WM_SIZEPARENT, 0, (LPARAM)&layout);
- }
- // if just getting the available rectangle, return it now...
- if (nFlags == reposQuery)
- {
- ASSERT(lpRectParam != NULL);
- if (bStretch)
- ::CopyRect(lpRectParam, &layout.rect);
- else
- {
- lpRectParam->left = lpRectParam->top = 0;
- lpRectParam->right = layout.sizeTotal.cx;
- lpRectParam->bottom = layout.sizeTotal.cy;
- }
- return;
- }
- // the rest is the client size of the left-over pane
- if (nIDLeftOver != 0 && hWndLeftOver != NULL)
- {
- CWnd* pLeftOver = CWnd::FromHandle(hWndLeftOver);
- // allow extra space as specified by lpRectBorder
- if (nFlags == reposExtra)
- {
- ASSERT(lpRectParam != NULL);
- layout.rect.left += lpRectParam->left;
- layout.rect.top += lpRectParam->top;
- layout.rect.right -= lpRectParam->right;
- layout.rect.bottom -= lpRectParam->bottom;
- }
- // reposition the window
- pLeftOver->CalcWindowRect(&layout.rect);
- AfxRepositionWindow(&layout, hWndLeftOver, &layout.rect);
- }
- // move and resize all the windows at once!
- if (layout.hDWP == NULL || !::EndDeferWindowPos(layout.hDWP))
- TRACE0("Warning: DeferWindowPos failed - low system resources.\n");
- }
- void AFXAPI AfxRepositionWindow(AFX_SIZEPARENTPARAMS* lpLayout,
- HWND hWnd, LPCRECT lpRect)
- {
- ASSERT(hWnd != NULL);
- ASSERT(lpRect != NULL);
- HWND hWndParent = ::GetParent(hWnd);
- ASSERT(hWndParent != NULL);
- if (lpLayout != NULL && lpLayout->hDWP == NULL)
- return;
- // first check if the new rectangle is the same as the current
- CRect rectOld;
- ::GetWindowRect(hWnd, rectOld);
- ::ScreenToClient(hWndParent, &rectOld.TopLeft());
- ::ScreenToClient(hWndParent, &rectOld.BottomRight());
- if (::EqualRect(rectOld, lpRect))
- return; // nothing to do
- // try to use DeferWindowPos for speed, otherwise use SetWindowPos
- if (lpLayout != NULL)
- {
- lpLayout->hDWP = ::DeferWindowPos(lpLayout->hDWP, hWnd, NULL,
- lpRect->left, lpRect->top, lpRect->right - lpRect->left,
- lpRect->bottom - lpRect->top, SWP_NOACTIVATE|SWP_NOZORDER);
- }
- else
- {
- ::SetWindowPos(hWnd, NULL, lpRect->left, lpRect->top,
- lpRect->right - lpRect->left, lpRect->bottom - lpRect->top,
- SWP_NOACTIVATE|SWP_NOZORDER);
- }
- }
- void CWnd::CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType)
- {
- DWORD dwExStyle = GetExStyle();
- if (nAdjustType == 0)
- dwExStyle &= ~WS_EX_CLIENTEDGE;
- ::AdjustWindowRectEx(lpClientRect, GetStyle(), FALSE, dwExStyle);
- }
- /////////////////////////////////////////////////////////////////////////////
- // Special keyboard/system command processing
- BOOL CWnd::HandleFloatingSysCommand(UINT nID, LPARAM lParam)
- {
- CWnd* pParent = GetTopLevelParent();
- switch (nID & 0xfff0)
- {
- case SC_PREVWINDOW:
- case SC_NEXTWINDOW:
- if (LOWORD(lParam) == VK_F6 && pParent != NULL)
- {
- pParent->SetFocus();
- return TRUE;
- }
- break;
- case SC_CLOSE:
- case SC_KEYMENU:
- // Check lParam. If it is 0L, then the user may have done
- // an Alt+Tab, so just ignore it. This breaks the ability to
- // just press the Alt-key and have the first menu selected,
- // but this is minor compared to what happens in the Alt+Tab
- // case.
- if ((nID & 0xfff0) == SC_CLOSE || lParam != 0L)
- {
- if (pParent != NULL)
- {
- // Sending the above WM_SYSCOMMAND may destroy the app,
- // so we have to be careful about restoring activation
- // and focus after sending it.
- HWND hWndSave = m_hWnd;
- HWND hWndFocus = ::GetFocus();
- pParent->SetActiveWindow();
- pParent->SendMessage(WM_SYSCOMMAND, nID, lParam);
- // be very careful here...
- if (::IsWindow(hWndSave))
- ::SetActiveWindow(hWndSave);
- if (::IsWindow(hWndFocus))
- ::SetFocus(hWndFocus);
- }
- }
- return TRUE;
- }
- return FALSE;
- }
- BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg)
- {
- ASSERT(hWndStop == NULL || ::IsWindow(hWndStop));
- ASSERT(pMsg != NULL);
- // walk from the target window up to the hWndStop window checking
- // if any window wants to translate this message
- for (HWND hWnd = pMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
- {
- CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
- if (pWnd != NULL)
- {
- // target window is a C++ window
- if (pWnd->PreTranslateMessage(pMsg))
- return TRUE; // trapped by target window (eg: accelerators)
- }
- // got to hWndStop window without interest
- if (hWnd == hWndStop)
- break;
- }
- return FALSE; // no special processing
- }
- BOOL CWnd::SendChildNotifyLastMsg(LRESULT* pResult)
- {
- _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
- return OnChildNotify(pThreadState->m_lastSentMsg.message,
- pThreadState->m_lastSentMsg.wParam, pThreadState->m_lastSentMsg.lParam, pResult);
- }
- BOOL PASCAL CWnd::ReflectLastMsg(HWND hWndChild, LRESULT* pResult)
- {
- // get the map, and if no map, then this message does not need reflection
- CHandleMap* pMap = afxMapHWND();
- if (pMap == NULL)
- return FALSE;
- // check if in permanent map, if it is reflect it (could be OLE control)
- CWnd* pWnd = (CWnd*)pMap->LookupPermanent(hWndChild);
- ASSERT(pWnd == NULL || pWnd->m_hWnd == hWndChild);
- if (pWnd == NULL)
- {
- #ifndef _AFX_NO_OCC_SUPPORT
- // check if the window is an OLE control
- CWnd* pWndParent = (CWnd*)pMap->LookupPermanent(::GetParent(hWndChild));
- if (pWndParent != NULL && pWndParent->m_pCtrlCont != NULL)
- {
- // If a matching control site exists, it's an OLE control
- COleControlSite* pSite = (COleControlSite*)pWndParent->
- m_pCtrlCont->m_siteMap.GetValueAt(hWndChild);
- if (pSite != NULL)
- {
- CWnd wndTemp(hWndChild);
- wndTemp.m_pCtrlSite = pSite;
- LRESULT lResult = wndTemp.SendChildNotifyLastMsg(pResult);
- wndTemp.m_hWnd = NULL;
- return lResult;
- }
- }
- #endif //!_AFX_NO_OCC_SUPPORT
- return FALSE;
- }
- // only OLE controls and permanent windows will get reflected msgs
- ASSERT(pWnd != NULL);
- return pWnd->SendChildNotifyLastMsg(pResult);
- }
- BOOL CWnd::OnChildNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
- {
- #ifndef _AFX_NO_OCC_SUPPORT
- if (m_pCtrlSite != NULL)
- {
- // first forward raw OCM_ messages to OLE control sources
- LRESULT lResult = SendMessage(OCM__BASE+uMsg, wParam, lParam);
- if (uMsg >= WM_CTLCOLORMSGBOX && uMsg <= WM_CTLCOLORSTATIC &&
- (HBRUSH)lResult == NULL)
- {
- // for WM_CTLCOLOR msgs, returning NULL implies continue routing
- return FALSE;
- }
- if (pResult != NULL)
- *pResult = lResult;
- return TRUE;
- }
- #endif
- return ReflectChildNotify(uMsg, wParam, lParam, pResult);
- }
- BOOL CWnd::ReflectChildNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
- {
- // Note: reflected messages are send directly to CWnd::OnWndMsg
- // and CWnd::OnCmdMsg for speed and because these messages are not
- // routed by normal OnCmdMsg routing (they are only dispatched)
- switch (uMsg)
- {
- // normal messages (just wParam, lParam through OnWndMsg)
- case WM_HSCROLL:
- case WM_VSCROLL:
- case WM_PARENTNOTIFY:
- case WM_DRAWITEM:
- case WM_MEASUREITEM:
- case WM_DELETEITEM:
- case WM_VKEYTOITEM:
- case WM_CHARTOITEM:
- case WM_COMPAREITEM:
- // reflect the message through the message map as WM_REFLECT_BASE+uMsg
- return CWnd::OnWndMsg(WM_REFLECT_BASE+uMsg, wParam, lParam, pResult);
- // special case for WM_COMMAND
- case WM_COMMAND:
- {
- // reflect the message through the message map as OCM_COMMAND
- int nCode = HIWORD(wParam);
- if (CWnd::OnCmdMsg(0, MAKELONG(nCode, WM_REFLECT_BASE+WM_COMMAND), NULL, NULL))
- {
- if (pResult != NULL)
- *pResult = 1;
- return TRUE;
- }
- }
- break;
- // special case for WM_NOTIFY
- case WM_NOTIFY:
- {
- // reflect the message through the message map as OCM_NOTIFY
- NMHDR* pNMHDR = (NMHDR*)lParam;
- int nCode = pNMHDR->code;
- AFX_NOTIFY notify;
- notify.pResult = pResult;
- notify.pNMHDR = pNMHDR;
- return CWnd::OnCmdMsg(0, MAKELONG(nCode, WM_REFLECT_BASE+WM_NOTIFY), ¬ify, NULL);
- }
- // other special cases (WM_CTLCOLOR family)
- default:
- if (uMsg >= WM_CTLCOLORMSGBOX && uMsg <= WM_CTLCOLORSTATIC)
- {
- // fill in special struct for compatiblity with 16-bit WM_CTLCOLOR
- AFX_CTLCOLOR ctl;
- ctl.hDC = (HDC)wParam;
- ctl.nCtlType = uMsg - WM_CTLCOLORMSGBOX;
- ASSERT(ctl.nCtlType >= CTLCOLOR_MSGBOX);
- ASSERT(ctl.nCtlType <= CTLCOLOR_STATIC);
- // reflect the message through the message map as OCM_CTLCOLOR
- BOOL bResult = CWnd::OnWndMsg(WM_REFLECT_BASE+WM_CTLCOLOR, 0, (LPARAM)&ctl, pResult);
- if ((HBRUSH)*pResult == NULL)
- bResult = FALSE;
- return bResult;
- }
- break;
- }
- return FALSE; // let the parent handle it
- }
- void CWnd::OnParentNotify(UINT message, LPARAM lParam)
- {
- if ((LOWORD(message) == WM_CREATE || LOWORD(message) == WM_DESTROY))
- {
- if (ReflectLastMsg((HWND)lParam))
- return; // eat it
- }
- // not handled - do default
- Default();
- }
- LRESULT CWnd::OnActivateTopLevel(WPARAM wParam, LPARAM)
- {
- if (LOWORD(wParam) == WA_INACTIVE)
- {
- _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
- if (!(pThreadState->m_lastInfo.uFlags & TTF_ALWAYSTIP))
- CancelToolTips(TRUE);
- }
- return 0;
- }
- void CWnd::OnSysColorChange()
- {
- CWinApp* pApp = AfxGetApp();
- if (pApp != NULL && pApp->m_pMainWnd == this)
- {
- // recolor global brushes used by control bars
- afxData.UpdateSysColors();
- }
- #ifndef _AFX_NO_CTL3D_SUPPORT
- if (!afxContextIsDLL)
- {
- if (AfxGetThread() != NULL && AfxGetThread()->m_pMainWnd == this)
- {
- _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
- // allow CTL3D32.DLL to be notified of color change
- if (pCtl3dState->m_pfnColorChange != NULL)
- (*pCtl3dState->m_pfnColorChange)();
- }
- }
- #endif
- // forward this message to all other child windows
- if (!(GetStyle() & WS_CHILD))
- SendMessageToDescendants(WM_SYSCOLORCHANGE, 0, 0L, TRUE, TRUE);
- Default();
- }
- BOOL _afxGotScrollLines;
- void CWnd::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
- {
- UNUSED_ALWAYS(uFlags);
- UNUSED_ALWAYS(lpszSection);
- #ifndef _AFX_NO_CTL3D_SUPPORT
- if (!afxContextIsDLL)
- {
- _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
- // allow CTL3D32.DLL to update from WIN.INI settings
- if (AfxGetThread() != NULL && AfxGetThread()->m_pMainWnd == this &&
- pCtl3dState->m_pfnWinIniChange != NULL)
- {
- (*pCtl3dState->m_pfnWinIniChange)();
- }
- }
- #endif
- // force refresh of settings that we cache
- _afxGotScrollLines = FALSE;
- CWnd::OnDisplayChange(0, 0); // to update system metrics, etc.
- }
- void CWnd::OnWinIniChange(LPCTSTR lpszSection)
- {
- UNUSED_ALWAYS(lpszSection);
- // this function is provided for backward compatibility only
- // it is called only in Windows NT 3.51; in Windows 95 and
- // Windows NT, OnSettingChange is called
- #ifndef _AFX_NO_CTL3D_SUPPORT
- if (!afxContextIsDLL)
- {
- _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
- // allow CTL3D32.DLL to update from WIN.INI settings
- if (AfxGetThread() != NULL && AfxGetThread()->m_pMainWnd == this &&
- pCtl3dState->m_pfnWinIniChange != NULL)
- {
- (*pCtl3dState->m_pfnWinIniChange)();
- }
- }
- #endif
- CWnd::OnDisplayChange(0, 0); // to update system metrics, etc.
- }
- void CWnd::OnDevModeChange(LPTSTR lpDeviceName)
- {
- CWinApp* pApp = AfxGetApp();
- if (pApp != NULL && pApp->m_pMainWnd == this)
- pApp->DevModeChange(lpDeviceName);
- // forward this message to all other child windows
- if (!(GetStyle() & WS_CHILD))
- {
- const MSG* pMsg = GetCurrentMessage();
- SendMessageToDescendants(pMsg->message, pMsg->wParam, pMsg->lParam,
- TRUE, TRUE);
- }
- }
- BOOL CWnd::OnHelpInfo(HELPINFO* /*pHelpInfo*/)
- {
- if (!(GetStyle() & WS_CHILD))
- {
- CWnd* pMainWnd = AfxGetMainWnd();
- if (pMainWnd != NULL &&
- GetKeyState(VK_SHIFT) >= 0 &&
- GetKeyState(VK_CONTROL) >= 0 &&
- GetKeyState(VK_MENU) >= 0)
- {
- pMainWnd->SendMessage(WM_COMMAND, ID_HELP);
- return TRUE;
- }
- }
- return Default();
- }
- LRESULT CWnd::OnDisplayChange(WPARAM, LPARAM)
- {
- // update metrics if this window is the main window
- if (AfxGetMainWnd() == this)
- {
- // update any system metrics cache
- afxData.UpdateSysMetrics();
- }
- // forward this message to all other child windows
- if (!(GetStyle() & WS_CHILD))
- {
- const MSG* pMsg = GetCurrentMessage();
- SendMessageToDescendants(pMsg->message, pMsg->wParam, pMsg->lParam,
- TRUE, TRUE);
- }
- return Default();
- }
- LRESULT CWnd::OnDragList(WPARAM, LPARAM lParam)
- {
- LPDRAGLISTINFO lpInfo = (LPDRAGLISTINFO)lParam;
- ASSERT(lpInfo != NULL);
- LRESULT lResult;
- if (ReflectLastMsg(lpInfo->hWnd, &lResult))
- return (int)lResult; // eat it
- // not handled - do default
- return (int)Default();
- }
- void CWnd::OnHScroll(UINT, UINT, CScrollBar* pScrollBar)
- {
- if (pScrollBar != NULL && pScrollBar->SendChildNotifyLastMsg())
- return; // eat it
- Default();
- }
- void CWnd::OnVScroll(UINT, UINT, CScrollBar* pScrollBar)
- {
- if (pScrollBar != NULL && pScrollBar->SendChildNotifyLastMsg())
- return; // eat it
- Default();
- }
- void CWnd::OnEnterIdle(UINT /*nWhy*/, CWnd* /*pWho*/)
- {
- // WINBUG: In some OLE inplace active scenarios, OLE will post a
- // message instead of sending it. This causes so many WM_ENTERIDLE
- // messages to be sent that tasks running in the background stop
- // running. By dispatching the pending WM_ENTERIDLE messages
- // when the first one is received, we trick Windows into thinking
- // that only one was really sent and dispatched.
- {
- MSG msg;
- while (PeekMessage(&msg, NULL, WM_ENTERIDLE, WM_ENTERIDLE, PM_REMOVE))
- DispatchMessage(&msg);
- }
- Default();
- }
- HBRUSH CWnd::OnCtlColor(CDC*, CWnd* pWnd, UINT)
- {
- ASSERT(pWnd != NULL && pWnd->m_hWnd != NULL);
- LRESULT lResult;
- if (pWnd->SendChildNotifyLastMsg(&lResult))
- return (HBRUSH)lResult; // eat it
- return (HBRUSH)Default();
- }
- #ifndef _AFX_NO_GRAYDLG_SUPPORT
- // special helper for Gray OnCtlColor routines
- HBRUSH CWnd::OnGrayCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
- {
- LRESULT lResult;
- if (pWnd->SendChildNotifyLastMsg(&lResult))
- return (HBRUSH)lResult; // eat it
- _AFX_WIN_STATE* pWinState = _afxWinState;
- if (!GrayCtlColor(pDC->m_hDC, pWnd->GetSafeHwnd(), nCtlColor,
- pWinState->m_hDlgBkBrush, pWinState->m_crDlgTextClr))
- return (HBRUSH)Default();
- return pWinState->m_hDlgBkBrush;
- }
- #endif //!_AFX_NO_GRAYDLG_SUPPORT
- // implementation of OnCtlColor for default gray backgrounds
- // (works for any window containing controls)
- // return value of FALSE means caller must call DefWindowProc's default
- // TRUE means that 'hbrGray' will be used and the appropriate text
- // ('clrText') and background colors are set.
- BOOL PASCAL CWnd::GrayCtlColor(HDC hDC, HWND hWnd, UINT nCtlColor,
- HBRUSH hbrGray, COLORREF clrText)
- {
- if (hDC == NULL)
- {
- // sometimes Win32 passes a NULL hDC in the WM_CTLCOLOR message.
- TRACE0("Warning: hDC is NULL in CWnd::GrayCtlColor; WM_CTLCOLOR not processed.\n");
- return FALSE;
- }
- if (hbrGray == NULL ||
- nCtlColor == CTLCOLOR_EDIT || nCtlColor == CTLCOLOR_MSGBOX ||
- nCtlColor == CTLCOLOR_SCROLLBAR)
- {
- return FALSE;
- }
- if (nCtlColor == CTLCOLOR_LISTBOX)
- {
- // only handle requests to draw the space between edit and drop button
- // in a drop-down combo (not a drop-down list)
- if (!_AfxIsComboBoxControl(hWnd, (UINT)CBS_DROPDOWN))
- return FALSE;
- }
- // set background color and return handle to brush
- LOGBRUSH logbrush;
- VERIFY(::GetObject(hbrGray, sizeof(LOGBRUSH), (LPVOID)&logbrush));
- ::SetBkColor(hDC, logbrush.lbColor);
- if (clrText == (COLORREF)-1)
- clrText = ::GetSysColor(COLOR_WINDOWTEXT); // normal text
- ::SetTextColor(hDC, clrText);
- return TRUE;
- }
- #ifndef _AFX_NO_CTL3D_SUPPORT
- LRESULT CWnd::OnQuery3dControls(WPARAM, LPARAM)
- {
- // This is message handler is not in CWnd's message map.
- // It is placed in various derived classes' message maps to enable
- // 3D controls for specific window types only.
- return 0xFFFF; // CTL3D_ALL
- }
- #endif
- /////////////////////////////////////////////////////////////////////////////
- // 'dialog data' support
- BOOL CWnd::UpdateData(BOOL bSaveAndValidate)
- {
- ASSERT(::IsWindow(m_hWnd)); // calling UpdateData before DoModal?
- CDataExchange dx(this, bSaveAndValidate);
- // prevent control notifications from being dispatched during UpdateData
- _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
- HWND hWndOldLockout = pThreadState->m_hLockoutNotifyWindow;
- ASSERT(hWndOldLockout != m_hWnd); // must not recurse
- pThreadState->m_hLockoutNotifyWindow = m_hWnd;
- BOOL bOK = FALSE; // assume failure
- TRY
- {
- DoDataExchange(&dx);
- bOK = TRUE; // it worked
- }
- CATCH(CUserException, e)
- {
- // validation failed - user already alerted, fall through
- ASSERT(!bOK);
- // Note: DELETE_EXCEPTION_(e) not required
- }
- AND_CATCH_ALL(e)
- {
- // validation failed due to OOM or other resource failure
- e->ReportError(MB_ICONEXCLAMATION, AFX_IDP_INTERNAL_FAILURE);
- ASSERT(!bOK);
- DELETE_EXCEPTION(e);
- }
- END_CATCH_ALL
- pThreadState->m_hLockoutNotifyWindow = hWndOldLockout;
- return bOK;
- }
- CDataExchange::CDataExchange(CWnd* pDlgWnd, BOOL bSaveAndValidate)
- {
- ASSERT_VALID(pDlgWnd);
- m_bSaveAndValidate = bSaveAndValidate;
- m_pDlgWnd = pDlgWnd;
- m_hWndLastControl = NULL;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Centering dialog support (works for any non-child window)
- void CWnd::CenterWindow(CWnd* pAlternateOwner)
- {
- ASSERT(::IsWindow(m_hWnd));
- // determine owner window to center against
- DWORD dwStyle = GetStyle();
- HWND hWndCenter = pAlternateOwner->GetSafeHwnd();
- if (pAlternateOwner == NULL)
- {
- if (dwStyle & WS_CHILD)
- hWndCenter = ::GetParent(m_hWnd);
- else
- hWndCenter = ::GetWindow(m_hWnd, GW_OWNER);
- if (hWndCenter != NULL)
- {
- // let parent determine alternate center window
- HWND hWndTemp =
- (HWND)::SendMessage(hWndCenter, WM_QUERYCENTERWND, 0, 0);
- if (hWndTemp != NULL)
- hWndCenter = hWndTemp;
- }
- }
- // get coordinates of the window relative to its parent
- CRect rcDlg;
- GetWindowRect(&rcDlg);
- CRect rcArea;
- CRect rcCenter;
- HWND hWndParent;
- if (!(dwStyle & WS_CHILD))
- {
- // don't center against invisible or minimized windows
- if (hWndCenter != NULL)
- {
- DWORD dwStyle = ::GetWindowLong(hWndCenter, GWL_STYLE);
- if (!(dwStyle & WS_VISIBLE) || (dwStyle & WS_MINIMIZE))
- hWndCenter = NULL;
- }
- MONITORINFO mi;
- mi.cbSize = sizeof(mi);
- // center within appropriate monitor coordinates
- if (hWndCenter == NULL)
- {
- HWND hwDefault = AfxGetMainWnd()->GetSafeHwnd();
- GetMonitorInfo(
- MonitorFromWindow(hwDefault, MONITOR_DEFAULTTOPRIMARY), &mi);
- rcCenter = mi.rcWork;
- rcArea = mi.rcWork;
- }
- else
- {
- ::GetWindowRect(hWndCenter, &rcCenter);
- GetMonitorInfo(
- MonitorFromWindow(hWndCenter, MONITOR_DEFAULTTONEAREST), &mi);
- rcArea = mi.rcWork;
- }
- }
- else
- {
- // center within parent client coordinates
- hWndParent = ::GetParent(m_hWnd);
- ASSERT(::IsWindow(hWndParent));
- ::GetClientRect(hWndParent, &rcArea);
- ASSERT(::IsWindow(hWndCenter));
- ::GetClientRect(hWndCenter, &rcCenter);
- ::MapWindowPoints(hWndCenter, hWndParent, (POINT*)&rcCenter, 2);
- }
- // find dialog's upper left based on rcCenter
- int xLeft = (rcCenter.left + rcCenter.right) / 2 - rcDlg.Width() / 2;
- int yTop = (rcCenter.top + rcCenter.bottom) / 2 - rcDlg.Height() / 2;
- // if the dialog is outside the screen, move it inside
- if (xLeft < rcArea.left)
- xLeft = rcArea.left;
- else if (xLeft + rcDlg.Width() > rcArea.right)
- xLeft = rcArea.right - rcDlg.Width();
- if (yTop < rcArea.top)
- yTop = rcArea.top;
- else if (yTop + rcDlg.Height() > rcArea.bottom)
- yTop = rcArea.bottom - rcDlg.Height();
- // map screen coordinates to child coordinates
- SetWindowPos(NULL, xLeft, yTop, -1, -1,
- SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
- }
- BOOL CWnd::CheckAutoCenter()
- {
- return TRUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Dialog initialization support
- BOOL CWnd::ExecuteDlgInit(LPCTSTR lpszResourceName)
- {
- // find resource handle
- LPVOID lpResource = NULL;
- HGLOBAL hResource = NULL;
- if (lpszResourceName != NULL)
- {
- HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_DLGINIT);
- HRSRC hDlgInit = ::FindResource(hInst, lpszResourceName, RT_DLGINIT);
- if (hDlgInit != NULL)
- {
- // load it
- hResource = LoadResource(hInst, hDlgInit);
- if (hResource == NULL)
- return FALSE;
- // lock it
- lpResource = LockResource(hResource);
- ASSERT(lpResource != NULL);
- }
- }
- // execute it
- BOOL bResult = ExecuteDlgInit(lpResource);
- // cleanup
- if (lpResource != NULL && hResource != NULL)
- {
- UnlockResource(hResource);
- FreeResource(hResource);
- }
- return bResult;
- }
- BOOL CWnd::ExecuteDlgInit(LPVOID lpResource)
- {
- BOOL bSuccess = TRUE;
- if (lpResource != NULL)
- {
- UNALIGNED WORD* lpnRes = (WORD*)lpResource;
- while (bSuccess && *lpnRes != 0)
- {
- WORD nIDC = *lpnRes++;
- WORD nMsg = *lpnRes++;
- DWORD dwLen = *((UNALIGNED DWORD*&)lpnRes)++;
- // In Win32 the WM_ messages have changed. They have
- // to be translated from the 32-bit values to 16-bit
- // values here.
- #define WIN16_LB_ADDSTRING 0x0401
- #define WIN16_CB_ADDSTRING 0x0403
- #define AFX_CB_ADDSTRING 0x1234
- // unfortunately, WIN16_CB_ADDSTRING == CBEM_INSERTITEM
- if (nMsg == AFX_CB_ADDSTRING)
- nMsg = CBEM_INSERTITEM;
- else if (nMsg == WIN16_LB_ADDSTRING)
- nMsg = LB_ADDSTRING;
- else if (nMsg == WIN16_CB_ADDSTRING)
- nMsg = CB_ADDSTRING;
- // check for invalid/unknown message types
- #ifdef _AFX_NO_OCC_SUPPORT
- ASSERT(nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING ||
- nMsg == CBEM_INSERTITEM);
- #else
- ASSERT(nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING ||
- nMsg == CBEM_INSERTITEM ||
- nMsg == WM_OCC_LOADFROMSTREAM ||
- nMsg == WM_OCC_LOADFROMSTREAM_EX ||
- nMsg == WM_OCC_LOADFROMSTORAGE ||
- nMsg == WM_OCC_LOADFROMSTORAGE_EX ||
- nMsg == WM_OCC_INITNEW);
- #endif
- #ifdef _DEBUG
- // For AddStrings, the count must exactly delimit the
- // string, including the NULL termination. This check
- // will not catch all mal-formed ADDSTRINGs, but will
- // catch some.
- if (nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING || nMsg == CBEM_INSERTITEM)
- ASSERT(*((LPBYTE)lpnRes + (UINT)dwLen - 1) == 0);
- #endif
- if (nMsg == CBEM_INSERTITEM)
- {
- USES_CONVERSION;
- COMBOBOXEXITEM item;
- item.mask = CBEIF_TEXT;
- item.iItem = -1;
- item.pszText = A2T(LPSTR(lpnRes));
- if (::SendDlgItemMessage(m_hWnd, nIDC, nMsg, 0, (LPARAM) &item) == -1)
- bSuccess = FALSE;
- }
- #ifndef _AFX_NO_OCC_SUPPORT
- else if (nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING)
- #endif // !_AFX_NO_OCC_SUPPORT
- {
- // List/Combobox returns -1 for error
- if (::SendDlgItemMessageA(m_hWnd, nIDC, nMsg, 0, (LPARAM) lpnRes) == -1)
- bSuccess = FALSE;
- }
- // skip past data
- lpnRes = (WORD*)((LPBYTE)lpnRes + (UINT)dwLen);
- }
- }
- // send update message to all controls after all other siblings loaded
- if (bSuccess)
- SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, FALSE, FALSE);
- return bSuccess;
- }
- void CWnd::UpdateDialogControls(CCmdTarget* pTarget, BOOL bDisableIfNoHndler)
- {
- CCmdUI state;
- CWnd wndTemp; // very temporary window just for CmdUI update
- // walk all the kids - assume the IDs are for buttons
- for (HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
- hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
- {
- // send to buttons
- wndTemp.m_hWnd = hWndChild; // quick and dirty attach
- state.m_nID = _AfxGetDlgCtrlID(hWndChild);
- state.m_pOther = &wndTemp;
- // check for reflect handlers in the child window
- CWnd* pWnd = CWnd::FromHandlePermanent(hWndChild);
- if (pWnd != NULL)
- {
- // call it directly to disable any routing
- if (pWnd->CWnd::OnCmdMsg(0, MAKELONG(-1,
- WM_COMMAND+WM_REFLECT_BASE), &state, NULL))
- continue;
- }
- // check for handlers in the parent window
- if (CWnd::OnCmdMsg(state.m_nID, CN_UPDATE_COMMAND_UI, &state, NULL))
- continue;
- // determine whether to disable when no handler exists
- BOOL bDisableTemp = bDisableIfNoHndler;
- if (bDisableTemp)
- {
- if ((wndTemp.SendMessage(WM_GETDLGCODE) & DLGC_BUTTON) == 0)
- {
- // non-button controls don't get automagically disabled
- bDisableTemp = FALSE;
- }
- else
- {
- // only certain button controls get automagically disabled
- UINT nStyle = (UINT)(wndTemp.GetStyle() & 0x0F);
- if (nStyle == (UINT)BS_AUTOCHECKBOX ||
- nStyle == (UINT)BS_AUTO3STATE ||
- nStyle == (UINT)BS_GROUPBOX ||
- nStyle == (UINT)BS_AUTORADIOBUTTON)
- {
- bDisableTemp = FALSE;
- }
- }
- }
- // check for handlers in the target (owner)
- state.DoUpdate(pTarget, bDisableTemp);
- }
- wndTemp.m_hWnd = NULL; // quick and dirty detach
- }
- BOOL CWnd::PreTranslateInput(LPMSG lpMsg)
- {
- ASSERT(::IsWindow(m_hWnd));
- // don't translate non-input events
- if ((lpMsg->message < WM_KEYFIRST || lpMsg->message > WM_KEYLAST) &&
- (lpMsg->message < WM_MOUSEFIRST || lpMsg->message > WM_MOUSELAST))
- return FALSE;
- return IsDialogMessage(lpMsg);
- }
- int CWnd::RunModalLoop(DWORD dwFlags)
- {
- ASSERT(::IsWindow(m_hWnd)); // window must be created
- ASSERT(!(m_nFlags & WF_MODALLOOP)); // window must not already be in modal state
- // for tracking the idle time state
- BOOL bIdle = TRUE;
- LONG lIdleCount = 0;
- BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) && !(GetStyle() & WS_VISIBLE);
- HWND hWndParent = ::GetParent(m_hWnd);
- m_nFlags |= (WF_MODALLOOP|WF_CONTINUEMODAL);
- MSG* pMsg = &AfxGetThread()->m_msgCur;
- // acquire and dispatch messages until the modal state is done
- for (;;)
- {
- ASSERT(ContinueModal());
- // phase1: check to see if we can do idle work
- while (bIdle &&
- !::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE))
- {
- ASSERT(ContinueModal());
- // show the dialog when the message queue goes idle
- if (bShowIdle)
- {
- ShowWindow(SW_SHOWNORMAL);
- UpdateWindow();
- bShowIdle = FALSE;
- }
- // call OnIdle while in bIdle state
- if (!(dwFlags & MLF_NOIDLEMSG) && hWndParent != NULL && lIdleCount == 0)
- {
- // send WM_ENTERIDLE to the parent
- ::SendMessage(hWndParent, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd);
- }
- if ((dwFlags & MLF_NOKICKIDLE) ||
- !SendMessage(WM_KICKIDLE, MSGF_DIALOGBOX, lIdleCount++))
- {
- // stop idle processing next time
- bIdle = FALSE;
- }
- }
- // phase2: pump messages while available
- do
- {
- ASSERT(ContinueModal());
- // pump message, but quit on WM_QUIT
- if (!AfxGetThread()->PumpMessage())
- {
- AfxPostQuitMessage(0);
- return -1;
- }
- // show the window when certain special messages rec'd
- if (bShowIdle &&
- (pMsg->message == 0x118 || pMsg->message == WM_SYSKEYDOWN))
- {
- ShowWindow(SW_SHOWNORMAL);
- UpdateWindow();
- bShowIdle = FALSE;
- }
- if (!ContinueModal())
- goto ExitModal;
- // reset "no idle" state after pumping "normal" message
- if (AfxGetThread()->IsIdleMessage(pMsg))
- {
- bIdle = TRUE;
- lIdleCount = 0;
- }
- } while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE));
- }
- ExitModal:
- m_nFlags &= ~(WF_MODALLOOP|WF_CONTINUEMODAL);
- return m_nModalResult;
- }
- BOOL CWnd::ContinueModal()
- {
- return m_nFlags & WF_CONTINUEMODAL;
- }
- void CWnd::EndModalLoop(int nResult)
- {
- ASSERT(::IsWindow(m_hWnd));
- // this result will be returned from CWnd::RunModalLoop
- m_nModalResult = nResult;
- // make sure a message goes through to exit the modal loop
- if (m_nFlags & WF_CONTINUEMODAL)
- {
- m_nFlags &= ~WF_CONTINUEMODAL;
- PostMessage(WM_NULL);
- }
- }
- #ifndef _AFX_NO_OCC_SUPPORT
- BOOL CWnd::SetOccDialogInfo(_AFX_OCC_DIALOG_INFO*)
- {
- ASSERT(FALSE); // this class doesn't support dialog creation
- return FALSE;
- }
- #endif
- /////////////////////////////////////////////////////////////////////////////
- // Standard init called by WinMain
- AFX_STATIC BOOL AFXAPI _AfxRegisterWithIcon(WNDCLASS* pWndCls,
- LPCTSTR lpszClassName, UINT nIDIcon)
- {
- pWndCls->lpszClassName = lpszClassName;
- HINSTANCE hInst = AfxFindResourceHandle(
- MAKEINTRESOURCE(nIDIcon), RT_GROUP_ICON);
- if ((pWndCls->hIcon = ::LoadIcon(hInst, MAKEINTRESOURCE(nIDIcon))) == NULL)
- {
- // use default icon
- pWndCls->hIcon = ::LoadIcon(NULL, IDI_APPLICATION);
- }
- return AfxRegisterClass(pWndCls);
- }
- LONG AFXAPI _AfxInitCommonControls(LPINITCOMMONCONTROLSEX lpInitCtrls, LONG fToRegister)
- {
- ASSERT(fToRegister != 0);
- #ifndef _AFXDLL
- HINSTANCE hInstBefore = ::GetModuleHandleA("COMCTL32.DLL");
- #endif
- // load the COMCTL32.DLL library because it may not be loaded yet (delayload)
- HINSTANCE hInst = ::LoadLibraryA("COMCTL32.DLL");
- if (hInst == NULL)
- return 0;
- LONG lResult = 0;
- // attempt to get/call InitCommonControlsEx
- BOOL (STDAPICALLTYPE* pfnInit)(LPINITCOMMONCONTROLSEX lpInitCtrls) = NULL;
- (FARPROC&)pfnInit = ::GetProcAddress(hInst, "InitCommonControlsEx");
- if (pfnInit == NULL)
- {
- // not there, so call InitCommonControls if possible
- if ((fToRegister & AFX_WIN95CTLS_MASK) == fToRegister)
- {
- InitCommonControls();
- lResult = AFX_WIN95CTLS_MASK;
- }
- }
- #ifdef _AFXDLL
- else if (InitCommonControlsEx(lpInitCtrls))
- #else
- else if ((*pfnInit)(lpInitCtrls))
- #endif
- {
- // InitCommonControlsEx was successful so return the full mask
- lResult = fToRegister;
- #ifndef _AFXDLL
- if (hInstBefore == NULL)
- {
- // In the case that we are statically linked and COMCTL32.DLL
- // was not loaded before we loaded it with LoadLibrary in this
- // function, that indicates that the calling module is linked
- // with /delayload:comctl32.dll, and in this case we have to do
- // something to cause COMCTL32.DLL to stay loaded. The only thing
- // we can do is to call a COMCTL32.DLL API which will cause the
- // CRT's delay load helpers to get called and will cause the DLL
- // to get loaded. We choose to call InitCommonControls because
- // it exists in the original COMCTL32.DLL and it doesn't really
- // do any harm to call it, except for the time it takes to
- // register the set of original Windows 95 classes.
- // If this isn't done our FreeLibrary call below will cause
- // COMCTL32.DLL to go away, undoing the registration.
- InitCommonControls();
- lResult |= AFX_WIN95CTLS_MASK;
- }
- #endif
- }
- // free the library reference and return the result
- FreeLibrary(hInst);
- return lResult;
- }
- BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)
- {
- // mask off all classes that are already registered
- AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
- fToRegister &= ~pModuleState->m_fRegisteredClasses;
- if (fToRegister == 0)
- return TRUE;
- LONG fRegisteredClasses = 0;
- // common initialization
- WNDCLASS wndcls;
- memset(&wndcls, 0, sizeof(WNDCLASS)); // start with NULL defaults
- wndcls.lpfnWndProc = DefWindowProc;
- wndcls.hInstance = AfxGetInstanceHandle();
- wndcls.hCursor = afxData.hcurArrow;
- INITCOMMONCONTROLSEX init;
- init.dwSize = sizeof(init);
- // work to register classes as specified by fToRegister, populate fRegisteredClasses as we go
- if (fToRegister & AFX_WND_REG)
- {
- // Child windows - no brush, no icon, safest default class styles
- wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
- wndcls.lpszClassName = _afxWnd;
- if (AfxRegisterClass(&wndcls))
- fRegisteredClasses |= AFX_WND_REG;
- }
- if (fToRegister & AFX_WNDOLECONTROL_REG)
- {
- // OLE Control windows - use parent DC for speed
- wndcls.style |= CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
- wndcls.lpszClassName = _afxWndOleControl;
- if (AfxRegisterClass(&wndcls))
- fRegisteredClasses |= AFX_WNDOLECONTROL_REG;
- }
- if (fToRegister & AFX_WNDCONTROLBAR_REG)
- {
- // Control bar windows
- wndcls.style = 0; // control bars don't handle double click
- wndcls.lpszClassName = _afxWndControlBar;
- wndcls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
- if (AfxRegisterClass(&wndcls))
- fRegisteredClasses |= AFX_WNDCONTROLBAR_REG;
- }
- if (fToRegister & AFX_WNDMDIFRAME_REG)
- {
- // MDI Frame window (also used for splitter window)
- wndcls.style = CS_DBLCLKS;
- wndcls.hbrBackground = NULL;
- if (_AfxRegisterWithIcon(&wndcls, _afxWndMDIFrame, AFX_IDI_STD_MDIFRAME))
- fRegisteredClasses |= AFX_WNDMDIFRAME_REG;
- }
- if (fToRegister & AFX_WNDFRAMEORVIEW_REG)
- {
- // SDI Frame or MDI Child windows or views - normal colors
- wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
- wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
- if (_AfxRegisterWithIcon(&wndcls, _afxWndFrameOrView, AFX_IDI_STD_FRAME))
- fRegisteredClasses |= AFX_WNDFRAMEORVIEW_REG;
- }
- if (fToRegister & AFX_WNDCOMMCTLS_REG)
- {
- // this flag is compatible with the old InitCommonControls() API
- init.dwICC = ICC_WIN95_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WIN95CTLS_MASK);
- fToRegister &= ~AFX_WIN95CTLS_MASK;
- }
- if (fToRegister & AFX_WNDCOMMCTL_UPDOWN_REG)
- {
- init.dwICC = ICC_UPDOWN_CLASS;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_UPDOWN_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_TREEVIEW_REG)
- {
- init.dwICC = ICC_TREEVIEW_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_TREEVIEW_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_TAB_REG)
- {
- init.dwICC = ICC_TAB_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_TAB_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_PROGRESS_REG)
- {
- init.dwICC = ICC_PROGRESS_CLASS;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_PROGRESS_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_LISTVIEW_REG)
- {
- init.dwICC = ICC_LISTVIEW_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_LISTVIEW_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_HOTKEY_REG)
- {
- init.dwICC = ICC_HOTKEY_CLASS;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_HOTKEY_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_BAR_REG)
- {
- init.dwICC = ICC_BAR_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_BAR_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_ANIMATE_REG)
- {
- init.dwICC = ICC_ANIMATE_CLASS;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_ANIMATE_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_INTERNET_REG)
- {
- init.dwICC = ICC_INTERNET_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_INTERNET_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_COOL_REG)
- {
- init.dwICC = ICC_COOL_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_COOL_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_USEREX_REG)
- {
- init.dwICC = ICC_USEREX_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_USEREX_REG);
- }
- if (fToRegister & AFX_WNDCOMMCTL_DATE_REG)
- {
- init.dwICC = ICC_DATE_CLASSES;
- fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_DATE_REG);
- }
- // save new state of registered controls
- pModuleState->m_fRegisteredClasses |= fRegisteredClasses;
- // special case for all common controls registered, turn on AFX_WNDCOMMCTLS_REG
- if ((pModuleState->m_fRegisteredClasses & AFX_WIN95CTLS_MASK) == AFX_WIN95CTLS_MASK)
- {
- pModuleState->m_fRegisteredClasses |= AFX_WNDCOMMCTLS_REG;
- fRegisteredClasses |= AFX_WNDCOMMCTLS_REG;
- }
- // must have registered at least as mamy classes as requested
- return (fToRegister & fRegisteredClasses) == fToRegister;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CFrameWnd (here for library granularity)
- BOOL CWnd::IsFrameWnd() const
- {
- return FALSE;
- }
- BOOL CFrameWnd::IsFrameWnd() const
- {
- return TRUE;
- }
- BOOL CFrameWnd::IsTracking() const
- {
- return m_nIDTracking != 0 &&
- m_nIDTracking != AFX_IDS_HELPMODEMESSAGE &&
- m_nIDTracking != AFX_IDS_IDLEMESSAGE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CTL3D support
- #ifndef _AFX_NO_CTL3D_SUPPORT
- // Use SubclassCtl3d to add CTL3D support to an already subclassed control
- // Usually only necessary if the control does not have one of the standard
- // Windows class names.
- BOOL CWnd::SubclassCtl3d(int nControlType)
- {
- ASSERT(!afxContextIsDLL); // Should only be called by apps
- if (afxContextIsDLL)
- return FALSE;
- ASSERT(m_hWnd != NULL);
- _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
- if (nControlType == -1)
- {
- if (pCtl3dState->m_pfnSubclassCtl != NULL)
- return (*pCtl3dState->m_pfnSubclassCtl)(m_hWnd);
- }
- else
- {
- if (pCtl3dState->m_pfnSubclassCtlEx != NULL)
- return (*pCtl3dState->m_pfnSubclassCtlEx)(m_hWnd, nControlType);
- }
- return FALSE;
- }
- // Use SubclassDlg3d to add CTL3D support to an entire window.
- // Any windows created on the window will be automatically subclassed.
- BOOL CWnd::SubclassDlg3d(DWORD dwMask)
- {
- ASSERT(!afxContextIsDLL); // Should only be called by apps
- if (afxContextIsDLL)
- return FALSE;
- ASSERT(m_hWnd != NULL);
- _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
- if (pCtl3dState->m_pfnSubclassDlgEx != NULL)
- return pCtl3dState->m_pfnSubclassDlgEx(m_hWnd, dwMask);
- return FALSE;
- }
- #endif //!_AFX_NO_CTL3D_SUPPORT
- //this function can't be inlined because of _afxShell
- void CWnd::DragAcceptFiles(BOOL bAccept)
- {
- ASSERT(::IsWindow(m_hWnd));
- ::DragAcceptFiles(m_hWnd, bAccept);
- }
- /////////////////////////////////////////////////////////////////////////////
- // Extra CWnd support for dynamic subclassing of controls
- BOOL CWnd::SubclassWindow(HWND hWnd)
- {
- if (!Attach(hWnd))
- return FALSE;
- // allow any other subclassing to occur
- PreSubclassWindow();
- // now hook into the AFX WndProc
- WNDPROC* lplpfn = GetSuperWndProcAddr();
- WNDPROC oldWndProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC,
- (DWORD)AfxGetAfxWndProc());
- ASSERT(oldWndProc != (WNDPROC)AfxGetAfxWndProc());
- if (*lplpfn == NULL)
- *lplpfn = oldWndProc; // the first control of that type created
- #ifdef _DEBUG
- else if (*lplpfn != oldWndProc)
- {
- TRACE0("Error: Trying to use SubclassWindow with incorrect CWnd\n");
- TRACE0("\tderived class.\n");
- TRACE3("\thWnd = $%04X (nIDC=$%04X) is not a %hs.\n", (UINT)hWnd,
- _AfxGetDlgCtrlID(hWnd), GetRuntimeClass()->m_lpszClassName);
- ASSERT(FALSE);
- // undo the subclassing if continuing after assert
- ::SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)oldWndProc);
- }
- #endif
- return TRUE;
- }
- BOOL CWnd::SubclassDlgItem(UINT nID, CWnd* pParent)
- {
- ASSERT(pParent != NULL);
- ASSERT(::IsWindow(pParent->m_hWnd));
- // check for normal dialog control first
- HWND hWndControl = ::GetDlgItem(pParent->m_hWnd, nID);
- if (hWndControl != NULL)
- return SubclassWindow(hWndControl);
- #ifndef _AFX_NO_OCC_SUPPORT
- if (pParent->m_pCtrlCont != NULL)
- {
- // normal dialog control not found
- COleControlSite* pSite = pParent->m_pCtrlCont->FindItem(nID);
- if (pSite != NULL)
- {
- ASSERT(pSite->m_hWnd != NULL);
- VERIFY(SubclassWindow(pSite->m_hWnd));
- #ifndef _AFX_NO_OCC_SUPPORT
- // If the control has reparented itself (e.g., invisible control),
- // make sure that the CWnd gets properly wired to its control site.
- if (pParent->m_hWnd != ::GetParent(pSite->m_hWnd))
- AttachControlSite(pParent);
- #endif //!_AFX_NO_OCC_SUPPORT
- return TRUE;
- }
- }
- #endif
- return FALSE; // control not found
- }
- HWND CWnd::UnsubclassWindow()
- {
- ASSERT(::IsWindow(m_hWnd));
- // set WNDPROC back to original value
- WNDPROC* lplpfn = GetSuperWndProcAddr();
- SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)*lplpfn);
- *lplpfn = NULL;
- // and Detach the HWND from the CWnd object
- return Detach();
- }
- ////////////////////////////////////////////////////////////////////////////
- // out-of-line inlines for binary compatibility
- #ifdef _AFXDLL
- #ifndef _DEBUG
- CPoint::CPoint(POINT initPt)
- { *(POINT*)this = initPt; }
- #endif
- #endif
- #ifdef AFX_INIT_SEG
- #pragma code_seg(AFX_INIT_SEG)
- #endif
- IMPLEMENT_DYNCREATE(CWnd, CCmdTarget)
- IMPLEMENT_DYNCREATE(CTempWnd, CWnd);
- #pragma warning(disable: 4074)
- #pragma init_seg(compiler)
- IMPLEMENT_FIXED_ALLOC(CTempWnd, 64);
- /////////////////////////////////////////////////////////////////////////////
|