wincore.cpp 107 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #ifndef _AFX_NO_OCC_SUPPORT
  12. #include "occimpl.h"
  13. #endif
  14. #pragma warning(disable:4706)
  15. #define COMPILE_MULTIMON_STUBS
  16. #include <multimon.h>
  17. #pragma warning(default:4706)
  18. #ifdef AFX_CORE1_SEG
  19. #pragma code_seg(AFX_CORE1_SEG)
  20. #endif
  21. #ifdef _DEBUG
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25. #define new DEBUG_NEW
  26. /////////////////////////////////////////////////////////////////////////////
  27. // Globals
  28. const UINT CWnd::m_nMsgDragList = ::RegisterWindowMessage(DRAGLISTMSGSTRING);
  29. // CWnds for setting z-order with SetWindowPos's pWndInsertAfter parameter
  30. const AFX_DATADEF CWnd CWnd::wndTop(HWND_TOP);
  31. const AFX_DATADEF CWnd CWnd::wndBottom(HWND_BOTTOM);
  32. const AFX_DATADEF CWnd CWnd::wndTopMost(HWND_TOPMOST);
  33. const AFX_DATADEF CWnd CWnd::wndNoTopMost(HWND_NOTOPMOST);
  34. const TCHAR _afxWnd[] = AFX_WND;
  35. const TCHAR _afxWndControlBar[] = AFX_WNDCONTROLBAR;
  36. const TCHAR _afxWndMDIFrame[] = AFX_WNDMDIFRAME;
  37. const TCHAR _afxWndFrameOrView[] = AFX_WNDFRAMEORVIEW;
  38. const TCHAR _afxWndOleControl[] = AFX_WNDOLECONTROL;
  39. /////////////////////////////////////////////////////////////////////////////
  40. // CWnd construction
  41. CWnd::CWnd()
  42. {
  43. AFX_ZERO_INIT_OBJECT(CCmdTarget);
  44. }
  45. CWnd::CWnd(HWND hWnd)
  46. {
  47. AFX_ZERO_INIT_OBJECT(CCmdTarget);
  48. m_hWnd = hWnd;
  49. }
  50. // Change a window's style
  51. AFX_STATIC BOOL AFXAPI _AfxModifyStyle(HWND hWnd, int nStyleOffset,
  52. DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  53. {
  54. ASSERT(hWnd != NULL);
  55. DWORD dwStyle = ::GetWindowLong(hWnd, nStyleOffset);
  56. DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
  57. if (dwStyle == dwNewStyle)
  58. return FALSE;
  59. ::SetWindowLong(hWnd, nStyleOffset, dwNewStyle);
  60. if (nFlags != 0)
  61. {
  62. ::SetWindowPos(hWnd, NULL, 0, 0, 0, 0,
  63. SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
  64. }
  65. return TRUE;
  66. }
  67. BOOL PASCAL
  68. CWnd::ModifyStyle(HWND hWnd, DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  69. {
  70. return _AfxModifyStyle(hWnd, GWL_STYLE, dwRemove, dwAdd, nFlags);
  71. }
  72. BOOL PASCAL
  73. CWnd::ModifyStyleEx(HWND hWnd, DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  74. {
  75. return _AfxModifyStyle(hWnd, GWL_EXSTYLE, dwRemove, dwAdd, nFlags);
  76. }
  77. /////////////////////////////////////////////////////////////////////////////
  78. // Special helpers for certain windows messages
  79. AFX_STATIC void AFXAPI _AfxPreInitDialog(
  80. CWnd* pWnd, LPRECT lpRectOld, DWORD* pdwStyleOld)
  81. {
  82. ASSERT(lpRectOld != NULL);
  83. ASSERT(pdwStyleOld != NULL);
  84. pWnd->GetWindowRect(lpRectOld);
  85. *pdwStyleOld = pWnd->GetStyle();
  86. }
  87. AFX_STATIC void AFXAPI _AfxPostInitDialog(
  88. CWnd* pWnd, const RECT& rectOld, DWORD dwStyleOld)
  89. {
  90. // must be hidden to start with
  91. if (dwStyleOld & WS_VISIBLE)
  92. return;
  93. // must not be visible after WM_INITDIALOG
  94. if (pWnd->GetStyle() & (WS_VISIBLE|WS_CHILD))
  95. return;
  96. // must not move during WM_INITDIALOG
  97. CRect rect;
  98. pWnd->GetWindowRect(rect);
  99. if (rectOld.left != rect.left || rectOld.top != rect.top)
  100. return;
  101. // must be unowned or owner disabled
  102. CWnd* pParent = pWnd->GetWindow(GW_OWNER);
  103. if (pParent != NULL && pParent->IsWindowEnabled())
  104. return;
  105. if (!pWnd->CheckAutoCenter())
  106. return;
  107. // center modal dialog boxes/message boxes
  108. pWnd->CenterWindow();
  109. }
  110. AFX_STATIC void AFXAPI
  111. _AfxHandleActivate(CWnd* pWnd, WPARAM nState, CWnd* pWndOther)
  112. {
  113. ASSERT(pWnd != NULL);
  114. // send WM_ACTIVATETOPLEVEL when top-level parents change
  115. CWnd* pTopLevel;
  116. if (!(pWnd->GetStyle() & WS_CHILD) &&
  117. (pTopLevel = pWnd->GetTopLevelParent()) != pWndOther->GetTopLevelParent())
  118. {
  119. // lParam points to window getting the WM_ACTIVATE message and
  120. // hWndOther from the WM_ACTIVATE.
  121. HWND hWnd2[2];
  122. hWnd2[0] = pWnd->m_hWnd;
  123. hWnd2[1] = pWndOther->GetSafeHwnd();
  124. // send it...
  125. pTopLevel->SendMessage(WM_ACTIVATETOPLEVEL, nState, (LPARAM)&hWnd2[0]);
  126. }
  127. }
  128. AFX_STATIC BOOL AFXAPI
  129. _AfxHandleSetCursor(CWnd* pWnd, UINT nHitTest, UINT nMsg)
  130. {
  131. if (nHitTest == HTERROR &&
  132. (nMsg == WM_LBUTTONDOWN || nMsg == WM_MBUTTONDOWN ||
  133. nMsg == WM_RBUTTONDOWN))
  134. {
  135. // activate the last active window if not active
  136. CWnd* pLastActive = pWnd->GetTopLevelParent();
  137. if (pLastActive != NULL)
  138. pLastActive = pLastActive->GetLastActivePopup();
  139. if (pLastActive != NULL &&
  140. pLastActive != CWnd::GetForegroundWindow() &&
  141. pLastActive->IsWindowEnabled())
  142. {
  143. pLastActive->SetForegroundWindow();
  144. return TRUE;
  145. }
  146. }
  147. return FALSE;
  148. }
  149. /////////////////////////////////////////////////////////////////////////////
  150. // Official way to send message to a CWnd
  151. LRESULT AFXAPI AfxCallWndProc(CWnd* pWnd, HWND hWnd, UINT nMsg,
  152. WPARAM wParam = 0, LPARAM lParam = 0)
  153. {
  154. _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  155. MSG oldState = pThreadState->m_lastSentMsg; // save for nesting
  156. pThreadState->m_lastSentMsg.hwnd = hWnd;
  157. pThreadState->m_lastSentMsg.message = nMsg;
  158. pThreadState->m_lastSentMsg.wParam = wParam;
  159. pThreadState->m_lastSentMsg.lParam = lParam;
  160. #ifdef _DEBUG
  161. if (afxTraceFlags & traceWinMsg)
  162. _AfxTraceMsg(_T("WndProc"), &pThreadState->m_lastSentMsg);
  163. #endif
  164. // Catch exceptions thrown outside the scope of a callback
  165. // in debug builds and warn the user.
  166. LRESULT lResult;
  167. TRY
  168. {
  169. #ifndef _AFX_NO_OCC_SUPPORT
  170. // special case for WM_DESTROY
  171. if ((nMsg == WM_DESTROY) && (pWnd->m_pCtrlCont != NULL))
  172. pWnd->m_pCtrlCont->OnUIActivate(NULL);
  173. #endif
  174. // special case for WM_INITDIALOG
  175. CRect rectOld;
  176. DWORD dwStyle = 0;
  177. if (nMsg == WM_INITDIALOG)
  178. _AfxPreInitDialog(pWnd, &rectOld, &dwStyle);
  179. // delegate to object's WindowProc
  180. lResult = pWnd->WindowProc(nMsg, wParam, lParam);
  181. // more special case for WM_INITDIALOG
  182. if (nMsg == WM_INITDIALOG)
  183. _AfxPostInitDialog(pWnd, rectOld, dwStyle);
  184. }
  185. CATCH_ALL(e)
  186. {
  187. lResult = AfxGetThread()->ProcessWndProcException(e, &pThreadState->m_lastSentMsg);
  188. TRACE1("Warning: Uncaught exception in WindowProc (returning %ld).\n",
  189. lResult);
  190. DELETE_EXCEPTION(e);
  191. }
  192. END_CATCH_ALL
  193. pThreadState->m_lastSentMsg = oldState;
  194. return lResult;
  195. }
  196. const MSG* PASCAL CWnd::GetCurrentMessage()
  197. {
  198. // fill in time and position when asked for
  199. _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  200. pThreadState->m_lastSentMsg.time = ::GetMessageTime();
  201. pThreadState->m_lastSentMsg.pt = CPoint(::GetMessagePos());
  202. return &pThreadState->m_lastSentMsg;
  203. }
  204. LRESULT CWnd::Default()
  205. {
  206. // call DefWindowProc with the last message
  207. _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  208. return DefWindowProc(pThreadState->m_lastSentMsg.message,
  209. pThreadState->m_lastSentMsg.wParam, pThreadState->m_lastSentMsg.lParam);
  210. }
  211. /////////////////////////////////////////////////////////////////////////////
  212. // Map from HWND to CWnd*
  213. #include "fixalloc.h"
  214. class CTempWnd : public CWnd
  215. {
  216. DECLARE_DYNCREATE(CTempWnd)
  217. DECLARE_FIXED_ALLOC(CTempWnd);
  218. };
  219. CHandleMap* PASCAL afxMapHWND(BOOL bCreate)
  220. {
  221. AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
  222. if (pState->m_pmapHWND == NULL && bCreate)
  223. {
  224. BOOL bEnable = AfxEnableMemoryTracking(FALSE);
  225. #ifndef _AFX_PORTABLE
  226. _PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler);
  227. #endif
  228. pState->m_pmapHWND = new CHandleMap(RUNTIME_CLASS(CTempWnd),
  229. offsetof(CWnd, m_hWnd));
  230. #ifndef _AFX_PORTABLE
  231. AfxSetNewHandler(pnhOldHandler);
  232. #endif
  233. AfxEnableMemoryTracking(bEnable);
  234. }
  235. return pState->m_pmapHWND;
  236. }
  237. CWnd* PASCAL CWnd::FromHandle(HWND hWnd)
  238. {
  239. CHandleMap* pMap = afxMapHWND(TRUE); //create map if not exist
  240. ASSERT(pMap != NULL);
  241. CWnd* pWnd = (CWnd*)pMap->FromHandle(hWnd);
  242. #ifndef _AFX_NO_OCC_SUPPORT
  243. pWnd->AttachControlSite(pMap);
  244. #endif
  245. ASSERT(pWnd == NULL || pWnd->m_hWnd == hWnd);
  246. return pWnd;
  247. }
  248. CWnd* PASCAL CWnd::FromHandlePermanent(HWND hWnd)
  249. {
  250. CHandleMap* pMap = afxMapHWND();
  251. CWnd* pWnd = NULL;
  252. if (pMap != NULL)
  253. {
  254. // only look in the permanent map - does no allocations
  255. pWnd = (CWnd*)pMap->LookupPermanent(hWnd);
  256. ASSERT(pWnd == NULL || pWnd->m_hWnd == hWnd);
  257. }
  258. return pWnd;
  259. }
  260. BOOL CWnd::Attach(HWND hWndNew)
  261. {
  262. ASSERT(m_hWnd == NULL); // only attach once, detach on destroy
  263. ASSERT(FromHandlePermanent(hWndNew) == NULL);
  264. // must not already be in permanent map
  265. if (hWndNew == NULL)
  266. return FALSE;
  267. CHandleMap* pMap = afxMapHWND(TRUE); // create map if not exist
  268. ASSERT(pMap != NULL);
  269. pMap->SetPermanent(m_hWnd = hWndNew, this);
  270. #ifndef _AFX_NO_OCC_SUPPORT
  271. AttachControlSite(pMap);
  272. #endif
  273. return TRUE;
  274. }
  275. HWND CWnd::Detach()
  276. {
  277. HWND hWnd = m_hWnd;
  278. if (hWnd != NULL)
  279. {
  280. CHandleMap* pMap = afxMapHWND(); // don't create if not exist
  281. if (pMap != NULL)
  282. pMap->RemoveHandle(m_hWnd);
  283. m_hWnd = NULL;
  284. }
  285. #ifndef _AFX_NO_OCC_SUPPORT
  286. m_pCtrlSite = NULL;
  287. #endif
  288. return hWnd;
  289. }
  290. void CWnd::PreSubclassWindow()
  291. {
  292. // no default processing
  293. }
  294. /////////////////////////////////////////////////////////////////////////////
  295. // The WndProc for all CWnd's and derived classes
  296. LRESULT CALLBACK
  297. AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
  298. {
  299. // special message which identifies the window as using AfxWndProc
  300. if (nMsg == WM_QUERYAFXWNDPROC)
  301. return 1;
  302. // all other messages route through message map
  303. CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
  304. ASSERT(pWnd != NULL);
  305. ASSERT(pWnd->m_hWnd == hWnd);
  306. return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);
  307. }
  308. // always indirectly accessed via AfxGetAfxWndProc
  309. WNDPROC AFXAPI AfxGetAfxWndProc()
  310. {
  311. #ifdef _AFXDLL
  312. return AfxGetModuleState()->m_pfnAfxWndProc;
  313. #else
  314. return &AfxWndProc;
  315. #endif
  316. }
  317. /////////////////////////////////////////////////////////////////////////////
  318. // Special WndProcs (activation handling & gray dialogs)
  319. AFX_STATIC_DATA const TCHAR _afxOldWndProc[] = _T("AfxOldWndProc423");
  320. LRESULT CALLBACK
  321. _AfxActivationWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
  322. {
  323. WNDPROC oldWndProc = (WNDPROC)::GetProp(hWnd, _afxOldWndProc);
  324. ASSERT(oldWndProc != NULL);
  325. LRESULT lResult = 0;
  326. TRY
  327. {
  328. BOOL bCallDefault = TRUE;
  329. switch (nMsg)
  330. {
  331. case WM_INITDIALOG:
  332. {
  333. DWORD dwStyle;
  334. CRect rectOld;
  335. CWnd* pWnd = CWnd::FromHandle(hWnd);
  336. _AfxPreInitDialog(pWnd, &rectOld, &dwStyle);
  337. bCallDefault = FALSE;
  338. lResult = CallWindowProc(oldWndProc, hWnd, nMsg, wParam, lParam);
  339. _AfxPostInitDialog(pWnd, rectOld, dwStyle);
  340. }
  341. break;
  342. case WM_ACTIVATE:
  343. _AfxHandleActivate(CWnd::FromHandle(hWnd), wParam,
  344. CWnd::FromHandle((HWND)lParam));
  345. break;
  346. case WM_SETCURSOR:
  347. bCallDefault = !_AfxHandleSetCursor(CWnd::FromHandle(hWnd),
  348. (short)LOWORD(lParam), HIWORD(lParam));
  349. break;
  350. case WM_NCDESTROY:
  351. SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)oldWndProc);
  352. RemoveProp(hWnd, _afxOldWndProc);
  353. GlobalDeleteAtom(GlobalFindAtom(_afxOldWndProc));
  354. break;
  355. }
  356. // call original wndproc for default handling
  357. if (bCallDefault)
  358. lResult = CallWindowProc(oldWndProc, hWnd, nMsg, wParam, lParam);
  359. }
  360. CATCH_ALL(e)
  361. {
  362. // handle exception
  363. MSG msg;
  364. msg.hwnd = hWnd;
  365. msg.message = nMsg;
  366. msg.wParam = wParam;
  367. msg.lParam = lParam;
  368. lResult = AfxGetThread()->ProcessWndProcException(e, &msg);
  369. TRACE1("Warning: Uncaught exception in _AfxActivationWndProc (returning %ld).\n",
  370. lResult);
  371. DELETE_EXCEPTION(e);
  372. }
  373. END_CATCH_ALL
  374. return lResult;
  375. }
  376. #ifndef _AFX_NO_GRAYDLG_SUPPORT
  377. LRESULT CALLBACK
  378. _AfxGrayBackgroundWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
  379. {
  380. // handle standard gray backgrounds if enabled
  381. _AFX_WIN_STATE* pWinState = _afxWinState;
  382. if (pWinState->m_hDlgBkBrush != NULL &&
  383. (nMsg == WM_CTLCOLORBTN || nMsg == WM_CTLCOLORDLG ||
  384. nMsg == WM_CTLCOLORSTATIC || nMsg == WM_CTLCOLORSCROLLBAR ||
  385. nMsg == WM_CTLCOLORLISTBOX) &&
  386. CWnd::GrayCtlColor((HDC)wParam, (HWND)lParam,
  387. (UINT)(nMsg - WM_CTLCOLORMSGBOX),
  388. pWinState->m_hDlgBkBrush, pWinState->m_crDlgTextClr))
  389. {
  390. return (LRESULT)pWinState->m_hDlgBkBrush;
  391. }
  392. // do standard activation related things as well
  393. return _AfxActivationWndProc(hWnd, nMsg, wParam, lParam);
  394. }
  395. #else //!_AFX_NO_GRAYDLG_SUPPORT
  396. #define _AfxGrayBackgroundWndProc _AfxActivationWndProc
  397. #endif //_AFX_NO_GRAYDLG_SUPPORT
  398. /////////////////////////////////////////////////////////////////////////////
  399. // Window creation hooks
  400. LRESULT CALLBACK
  401. _AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam)
  402. {
  403. _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  404. if (code != HCBT_CREATEWND)
  405. {
  406. // wait for HCBT_CREATEWND just pass others on...
  407. return CallNextHookEx(pThreadState->m_hHookOldCbtFilter, code,
  408. wParam, lParam);
  409. }
  410. ASSERT(lParam != NULL);
  411. LPCREATESTRUCT lpcs = ((LPCBT_CREATEWND)lParam)->lpcs;
  412. ASSERT(lpcs != NULL);
  413. CWnd* pWndInit = pThreadState->m_pWndInit;
  414. BOOL bContextIsDLL = afxContextIsDLL;
  415. if (pWndInit != NULL || (!(lpcs->style & WS_CHILD) && !bContextIsDLL))
  416. {
  417. // Note: special check to avoid subclassing the IME window
  418. if (_afxDBCS)
  419. {
  420. // check for cheap CS_IME style first...
  421. if (GetClassLong((HWND)wParam, GCL_STYLE) & CS_IME)
  422. goto lCallNextHook;
  423. // get class name of the window that is being created
  424. LPCTSTR pszClassName;
  425. TCHAR szClassName[_countof("ime")+1];
  426. if (HIWORD(lpcs->lpszClass))
  427. {
  428. pszClassName = lpcs->lpszClass;
  429. }
  430. else
  431. {
  432. szClassName[0] = '\0';
  433. GlobalGetAtomName((ATOM)lpcs->lpszClass, szClassName, _countof(szClassName));
  434. pszClassName = szClassName;
  435. }
  436. // a little more expensive to test this way, but necessary...
  437. if (lstrcmpi(pszClassName, _T("ime")) == 0)
  438. goto lCallNextHook;
  439. }
  440. ASSERT(wParam != NULL); // should be non-NULL HWND
  441. HWND hWnd = (HWND)wParam;
  442. WNDPROC oldWndProc;
  443. if (pWndInit != NULL)
  444. {
  445. #ifdef _AFXDLL
  446. AFX_MANAGE_STATE(pWndInit->m_pModuleState);
  447. #endif
  448. // the window should not be in the permanent map at this time
  449. ASSERT(CWnd::FromHandlePermanent(hWnd) == NULL);
  450. // connect the HWND to pWndInit...
  451. pWndInit->Attach(hWnd);
  452. // allow other subclassing to occur first
  453. pWndInit->PreSubclassWindow();
  454. WNDPROC *pOldWndProc = pWndInit->GetSuperWndProcAddr();
  455. ASSERT(pOldWndProc != NULL);
  456. #ifndef _AFX_NO_CTL3D_SUPPORT
  457. _AFX_CTL3D_STATE* pCtl3dState;
  458. DWORD dwFlags;
  459. if (!afxData.bWin4 && !bContextIsDLL &&
  460. (pCtl3dState = _afxCtl3dState.GetDataNA()) != NULL &&
  461. pCtl3dState->m_pfnSubclassDlgEx != NULL &&
  462. (dwFlags = AfxCallWndProc(pWndInit, hWnd, WM_QUERY3DCONTROLS)) != 0)
  463. {
  464. // was the class registered with AfxWndProc?
  465. WNDPROC afxWndProc = AfxGetAfxWndProc();
  466. BOOL bAfxWndProc = ((WNDPROC)
  467. GetWindowLong(hWnd, GWL_WNDPROC) == afxWndProc);
  468. pCtl3dState->m_pfnSubclassDlgEx(hWnd, dwFlags);
  469. // subclass the window if not already wired to AfxWndProc
  470. if (!bAfxWndProc)
  471. {
  472. // subclass the window with standard AfxWndProc
  473. oldWndProc = (WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC,
  474. (DWORD)afxWndProc);
  475. ASSERT(oldWndProc != NULL);
  476. *pOldWndProc = oldWndProc;
  477. }
  478. }
  479. else
  480. #endif
  481. {
  482. // subclass the window with standard AfxWndProc
  483. WNDPROC afxWndProc = AfxGetAfxWndProc();
  484. oldWndProc = (WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC,
  485. (DWORD)afxWndProc);
  486. ASSERT(oldWndProc != NULL);
  487. if (oldWndProc != afxWndProc)
  488. *pOldWndProc = oldWndProc;
  489. }
  490. pThreadState->m_pWndInit = NULL;
  491. }
  492. else
  493. {
  494. ASSERT(!bContextIsDLL); // should never get here
  495. // subclass the window with the proc which does gray backgrounds
  496. oldWndProc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);
  497. if (oldWndProc != NULL && GetProp(hWnd, _afxOldWndProc) == NULL)
  498. {
  499. SetProp(hWnd, _afxOldWndProc, oldWndProc);
  500. if ((WNDPROC)GetProp(hWnd, _afxOldWndProc) == oldWndProc)
  501. {
  502. GlobalAddAtom(_afxOldWndProc);
  503. SetWindowLong(hWnd, GWL_WNDPROC,
  504. (DWORD)(pThreadState->m_bDlgCreate ?
  505. _AfxGrayBackgroundWndProc : _AfxActivationWndProc));
  506. ASSERT(oldWndProc != NULL);
  507. }
  508. }
  509. }
  510. }
  511. lCallNextHook:
  512. LRESULT lResult = CallNextHookEx(pThreadState->m_hHookOldCbtFilter, code,
  513. wParam, lParam);
  514. #ifndef _AFXDLL
  515. if (bContextIsDLL)
  516. {
  517. ::UnhookWindowsHookEx(pThreadState->m_hHookOldCbtFilter);
  518. pThreadState->m_hHookOldCbtFilter = NULL;
  519. }
  520. #endif
  521. return lResult;
  522. }
  523. void AFXAPI AfxHookWindowCreate(CWnd* pWnd)
  524. {
  525. _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  526. if (pThreadState->m_pWndInit == pWnd)
  527. return;
  528. if (pThreadState->m_hHookOldCbtFilter == NULL)
  529. {
  530. pThreadState->m_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT,
  531. _AfxCbtFilterHook, NULL, ::GetCurrentThreadId());
  532. if (pThreadState->m_hHookOldCbtFilter == NULL)
  533. AfxThrowMemoryException();
  534. }
  535. ASSERT(pThreadState->m_hHookOldCbtFilter != NULL);
  536. ASSERT(pWnd != NULL);
  537. ASSERT(pWnd->m_hWnd == NULL); // only do once
  538. ASSERT(pThreadState->m_pWndInit == NULL); // hook not already in progress
  539. pThreadState->m_pWndInit = pWnd;
  540. }
  541. BOOL AFXAPI AfxUnhookWindowCreate()
  542. {
  543. _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  544. #ifndef _AFXDLL
  545. if (afxContextIsDLL && pThreadState->m_hHookOldCbtFilter != NULL)
  546. {
  547. ::UnhookWindowsHookEx(pThreadState->m_hHookOldCbtFilter);
  548. pThreadState->m_hHookOldCbtFilter = NULL;
  549. }
  550. #endif
  551. if (pThreadState->m_pWndInit != NULL)
  552. {
  553. pThreadState->m_pWndInit = NULL;
  554. return FALSE; // was not successfully hooked
  555. }
  556. return TRUE;
  557. }
  558. /////////////////////////////////////////////////////////////////////////////
  559. // CWnd creation
  560. BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
  561. LPCTSTR lpszWindowName, DWORD dwStyle,
  562. const RECT& rect, CWnd* pParentWnd, UINT nID,
  563. LPVOID lpParam /* = NULL */)
  564. {
  565. return CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
  566. rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
  567. pParentWnd->GetSafeHwnd(), (HMENU)nID, lpParam);
  568. }
  569. BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
  570. LPCTSTR lpszWindowName, DWORD dwStyle,
  571. int x, int y, int nWidth, int nHeight,
  572. HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
  573. {
  574. // allow modification of several common create parameters
  575. CREATESTRUCT cs;
  576. cs.dwExStyle = dwExStyle;
  577. cs.lpszClass = lpszClassName;
  578. cs.lpszName = lpszWindowName;
  579. cs.style = dwStyle;
  580. cs.x = x;
  581. cs.y = y;
  582. cs.cx = nWidth;
  583. cs.cy = nHeight;
  584. cs.hwndParent = hWndParent;
  585. cs.hMenu = nIDorHMenu;
  586. cs.hInstance = AfxGetInstanceHandle();
  587. cs.lpCreateParams = lpParam;
  588. if (!PreCreateWindow(cs))
  589. {
  590. PostNcDestroy();
  591. return FALSE;
  592. }
  593. AfxHookWindowCreate(this);
  594. HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,
  595. cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
  596. cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);
  597. #ifdef _DEBUG
  598. if (hWnd == NULL)
  599. {
  600. TRACE1("Warning: Window creation failed: GetLastError returns 0x%8.8X\n",
  601. GetLastError());
  602. }
  603. #endif
  604. if (!AfxUnhookWindowCreate())
  605. PostNcDestroy(); // cleanup if CreateWindowEx fails too soon
  606. if (hWnd == NULL)
  607. return FALSE;
  608. ASSERT(hWnd == m_hWnd); // should have been set in send msg hook
  609. return TRUE;
  610. }
  611. // for child windows
  612. BOOL CWnd::PreCreateWindow(CREATESTRUCT& cs)
  613. {
  614. if (cs.lpszClass == NULL)
  615. {
  616. // make sure the default window class is registered
  617. VERIFY(AfxDeferRegisterClass(AFX_WND_REG));
  618. // no WNDCLASS provided - use child window default
  619. ASSERT(cs.style & WS_CHILD);
  620. cs.lpszClass = _afxWnd;
  621. }
  622. return TRUE;
  623. }
  624. BOOL CWnd::Create(LPCTSTR lpszClassName,
  625. LPCTSTR lpszWindowName, DWORD dwStyle,
  626. const RECT& rect,
  627. CWnd* pParentWnd, UINT nID,
  628. CCreateContext* pContext)
  629. {
  630. // can't use for desktop or pop-up windows (use CreateEx instead)
  631. ASSERT(pParentWnd != NULL);
  632. ASSERT((dwStyle & WS_POPUP) == 0);
  633. return CreateEx(0, lpszClassName, lpszWindowName,
  634. dwStyle | WS_CHILD,
  635. rect.left, rect.top,
  636. rect.right - rect.left, rect.bottom - rect.top,
  637. pParentWnd->GetSafeHwnd(), (HMENU)nID, (LPVOID)pContext);
  638. }
  639. CWnd::~CWnd()
  640. {
  641. if (m_hWnd != NULL &&
  642. this != (CWnd*)&wndTop && this != (CWnd*)&wndBottom &&
  643. this != (CWnd*)&wndTopMost && this != (CWnd*)&wndNoTopMost)
  644. {
  645. TRACE(_T("Warning: calling DestroyWindow in CWnd::~CWnd; ")
  646. _T("OnDestroy or PostNcDestroy in derived class will not be called.\n"));
  647. DestroyWindow();
  648. }
  649. #ifndef _AFX_NO_OCC_SUPPORT
  650. // cleanup control container,
  651. // including destroying controls
  652. delete m_pCtrlCont;
  653. // cleanup control site
  654. if (m_pCtrlSite != NULL && m_pCtrlSite->m_pWndCtrl == this)
  655. m_pCtrlSite->m_pWndCtrl = NULL;
  656. #endif
  657. }
  658. void CWnd::OnDestroy()
  659. {
  660. #ifndef _AFX_NO_OCC_SUPPORT
  661. // cleanup control container
  662. delete m_pCtrlCont;
  663. m_pCtrlCont = NULL;
  664. #endif
  665. Default();
  666. }
  667. // WM_NCDESTROY is the absolute LAST message sent.
  668. void CWnd::OnNcDestroy()
  669. {
  670. // cleanup main and active windows
  671. CWinThread* pThread = AfxGetThread();
  672. if (pThread != NULL)
  673. {
  674. if (pThread->m_pMainWnd == this)
  675. {
  676. if (!afxContextIsDLL)
  677. {
  678. // shut down current thread if possible
  679. if (pThread != AfxGetApp() || AfxOleCanExitApp())
  680. AfxPostQuitMessage(0);
  681. }
  682. pThread->m_pMainWnd = NULL;
  683. }
  684. if (pThread->m_pActiveWnd == this)
  685. pThread->m_pActiveWnd = NULL;
  686. }
  687. #ifndef _AFX_NO_OLE_SUPPORT
  688. // cleanup OLE drop target interface
  689. if (m_pDropTarget != NULL)
  690. {
  691. m_pDropTarget->Revoke();
  692. m_pDropTarget = NULL;
  693. }
  694. #endif
  695. #ifndef _AFX_NO_OCC_SUPPORT
  696. // cleanup control container
  697. delete m_pCtrlCont;
  698. m_pCtrlCont = NULL;
  699. #endif
  700. // cleanup tooltip support
  701. if (m_nFlags & WF_TOOLTIPS)
  702. {
  703. CToolTipCtrl* pToolTip = AfxGetThreadState()->m_pToolTip;
  704. if (pToolTip->GetSafeHwnd() != NULL)
  705. {
  706. TOOLINFO ti; memset(&ti, 0, sizeof(TOOLINFO));
  707. ti.cbSize = sizeof(AFX_OLDTOOLINFO);
  708. ti.uFlags = TTF_IDISHWND;
  709. ti.hwnd = m_hWnd;
  710. ti.uId = (UINT)m_hWnd;
  711. pToolTip->SendMessage(TTM_DELTOOL, 0, (LPARAM)&ti);
  712. }
  713. }
  714. // call default, unsubclass, and detach from the map
  715. LONG pfnWndProc = GetWindowLong(m_hWnd, GWL_WNDPROC);
  716. Default();
  717. if (GetWindowLong(m_hWnd, GWL_WNDPROC) == pfnWndProc)
  718. {
  719. WNDPROC pfnSuper = *GetSuperWndProcAddr();
  720. if (pfnSuper != NULL)
  721. SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)pfnSuper);
  722. }
  723. Detach();
  724. ASSERT(m_hWnd == NULL);
  725. // call special post-cleanup routine
  726. PostNcDestroy();
  727. }
  728. void CWnd::PostNcDestroy()
  729. {
  730. // default to nothing
  731. }
  732. void CWnd::OnFinalRelease()
  733. {
  734. if (m_hWnd != NULL)
  735. DestroyWindow(); // will call PostNcDestroy
  736. else
  737. PostNcDestroy();
  738. }
  739. #ifdef _DEBUG
  740. void CWnd::AssertValid() const
  741. {
  742. if (m_hWnd == NULL)
  743. return; // null (unattached) windows are valid
  744. // check for special wnd??? values
  745. ASSERT(HWND_TOP == NULL); // same as desktop
  746. if (m_hWnd == HWND_BOTTOM)
  747. ASSERT(this == &CWnd::wndBottom);
  748. else if (m_hWnd == HWND_TOPMOST)
  749. ASSERT(this == &CWnd::wndTopMost);
  750. else if (m_hWnd == HWND_NOTOPMOST)
  751. ASSERT(this == &CWnd::wndNoTopMost);
  752. else
  753. {
  754. // should be a normal window
  755. ASSERT(::IsWindow(m_hWnd));
  756. // should also be in the permanent or temporary handle map
  757. CHandleMap* pMap = afxMapHWND();
  758. ASSERT(pMap != NULL);
  759. CObject* p;
  760. ASSERT((p = pMap->LookupPermanent(m_hWnd)) != NULL ||
  761. (p = pMap->LookupTemporary(m_hWnd)) != NULL);
  762. ASSERT((CWnd*)p == this); // must be us
  763. // Note: if either of the above asserts fire and you are
  764. // writing a multithreaded application, it is likely that
  765. // you have passed a C++ object from one thread to another
  766. // and have used that object in a way that was not intended.
  767. // (only simple inline wrapper functions should be used)
  768. //
  769. // In general, CWnd objects should be passed by HWND from
  770. // one thread to another. The receiving thread can wrap
  771. // the HWND with a CWnd object by using CWnd::FromHandle.
  772. //
  773. // It is dangerous to pass C++ objects from one thread to
  774. // another, unless the objects are designed to be used in
  775. // such a manner.
  776. }
  777. }
  778. void CWnd::Dump(CDumpContext& dc) const
  779. {
  780. CObject::Dump(dc);
  781. dc << "\nm_hWnd = " << (UINT)m_hWnd;
  782. if (m_hWnd == NULL || m_hWnd == HWND_BOTTOM ||
  783. m_hWnd == HWND_TOPMOST || m_hWnd == HWND_NOTOPMOST)
  784. {
  785. // not a normal window - nothing more to dump
  786. return;
  787. }
  788. if (!::IsWindow(m_hWnd))
  789. {
  790. // not a valid window
  791. dc << " (illegal HWND)";
  792. return; // don't do anything more
  793. }
  794. CWnd* pWnd = CWnd::FromHandlePermanent(m_hWnd);
  795. if (pWnd != this)
  796. dc << " (Detached or temporary window)";
  797. else
  798. dc << " (permanent window)";
  799. // dump out window specific statistics
  800. TCHAR szBuf [64];
  801. if (!::SendMessage(m_hWnd, WM_QUERYAFXWNDPROC, 0, 0) && pWnd == this)
  802. GetWindowText(szBuf, _countof(szBuf));
  803. else
  804. ::DefWindowProc(m_hWnd, WM_GETTEXT, _countof(szBuf), (LPARAM)&szBuf[0]);
  805. dc << "\ncaption = \"" << szBuf << "\"";
  806. ::GetClassName(m_hWnd, szBuf, _countof(szBuf));
  807. dc << "\nclass name = \"" << szBuf << "\"";
  808. CRect rect;
  809. GetWindowRect(&rect);
  810. dc << "\nrect = " << rect;
  811. dc << "\nparent CWnd* = " << (void*)GetParent();
  812. dc << "\nstyle = " << (void*)::GetWindowLong(m_hWnd, GWL_STYLE);
  813. if (::GetWindowLong(m_hWnd, GWL_STYLE) & WS_CHILD)
  814. dc << "\nid = " << _AfxGetDlgCtrlID(m_hWnd);
  815. dc << "\n";
  816. }
  817. #endif
  818. BOOL CWnd::DestroyWindow()
  819. {
  820. if (m_hWnd == NULL)
  821. return FALSE;
  822. CHandleMap* pMap = afxMapHWND();
  823. ASSERT(pMap != NULL);
  824. CWnd* pWnd = (CWnd*)pMap->LookupPermanent(m_hWnd);
  825. #ifdef _DEBUG
  826. HWND hWndOrig = m_hWnd;
  827. #endif
  828. #ifdef _AFX_NO_OCC_SUPPORT
  829. BOOL bResult = ::DestroyWindow(m_hWnd);
  830. #else //_AFX_NO_OCC_SUPPORT
  831. BOOL bResult;
  832. if (m_pCtrlSite == NULL)
  833. bResult = ::DestroyWindow(m_hWnd);
  834. else
  835. bResult = m_pCtrlSite->DestroyControl();
  836. #endif //_AFX_NO_OCC_SUPPORT
  837. // Note that 'this' may have been deleted at this point,
  838. // (but only if pWnd != NULL)
  839. if (pWnd != NULL)
  840. {
  841. // Should have been detached by OnNcDestroy
  842. #ifdef _DEBUG
  843. ASSERT(pMap->LookupPermanent(hWndOrig) == NULL);
  844. #endif
  845. }
  846. else
  847. {
  848. #ifdef _DEBUG
  849. ASSERT(m_hWnd == hWndOrig);
  850. #endif
  851. // Detach after DestroyWindow called just in case
  852. Detach();
  853. }
  854. return bResult;
  855. }
  856. /////////////////////////////////////////////////////////////////////////////
  857. // Default CWnd implementation
  858. LRESULT CWnd::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
  859. {
  860. if (m_pfnSuper != NULL)
  861. return ::CallWindowProc(m_pfnSuper, m_hWnd, nMsg, wParam, lParam);
  862. WNDPROC pfnWndProc;
  863. if ((pfnWndProc = *GetSuperWndProcAddr()) == NULL)
  864. return ::DefWindowProc(m_hWnd, nMsg, wParam, lParam);
  865. else
  866. return ::CallWindowProc(pfnWndProc, m_hWnd, nMsg, wParam, lParam);
  867. }
  868. WNDPROC* CWnd::GetSuperWndProcAddr()
  869. {
  870. // Note: it is no longer necessary to override GetSuperWndProcAddr
  871. // for each control class with a different WNDCLASS.
  872. // This implementation now uses instance data, such that the previous
  873. // WNDPROC can be anything.
  874. return &m_pfnSuper;
  875. }
  876. BOOL CWnd::PreTranslateMessage(MSG* pMsg)
  877. {
  878. // handle tooltip messages (some messages cancel, some may cause it to popup)
  879. AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
  880. if (pModuleState->m_pfnFilterToolTipMessage != NULL)
  881. (*pModuleState->m_pfnFilterToolTipMessage)(pMsg, this);
  882. // no default processing
  883. return FALSE;
  884. }
  885. void PASCAL CWnd::CancelToolTips(BOOL bKeys)
  886. {
  887. // check for active tooltip
  888. _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
  889. CToolTipCtrl* pToolTip = pThreadState->m_pToolTip;
  890. if (pToolTip->GetSafeHwnd() != NULL)
  891. pToolTip->SendMessage(TTM_ACTIVATE, FALSE);
  892. // check for active control bar fly-by status
  893. CControlBar* pLastStatus = pThreadState->m_pLastStatus;
  894. if (bKeys && pLastStatus != NULL && GetKeyState(VK_LBUTTON) >= 0)
  895. pLastStatus->SetStatusText(-1);
  896. }
  897. int CWnd::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
  898. {
  899. // find child window which hits the point
  900. // (don't use WindowFromPoint, because it ignores disabled windows)
  901. HWND hWndChild = _AfxChildWindowFromPoint(m_hWnd, point);
  902. if (hWndChild != NULL)
  903. {
  904. // return positive hit if control ID isn't -1
  905. int nHit = _AfxGetDlgCtrlID(hWndChild);
  906. // hits against child windows always center the tip
  907. if (pTI != NULL && pTI->cbSize >= sizeof(AFX_OLDTOOLINFO))
  908. {
  909. // setup the TOOLINFO structure
  910. pTI->hwnd = m_hWnd;
  911. pTI->uId = (UINT)hWndChild;
  912. pTI->uFlags |= TTF_IDISHWND;
  913. pTI->lpszText = LPSTR_TEXTCALLBACK;
  914. // set TTF_NOTBUTTON and TTF_CENTERTIP if it isn't a button
  915. if (!(::SendMessage(hWndChild, WM_GETDLGCODE, 0, 0) & DLGC_BUTTON))
  916. pTI->uFlags |= TTF_NOTBUTTON|TTF_CENTERTIP;
  917. }
  918. return nHit;
  919. }
  920. return -1; // not found
  921. }
  922. void CWnd::GetWindowText(CString& rString) const
  923. {
  924. ASSERT(::IsWindow(m_hWnd));
  925. #ifndef _AFX_NO_OCC_SUPPORT
  926. if (m_pCtrlSite == NULL)
  927. {
  928. #endif
  929. int nLen = ::GetWindowTextLength(m_hWnd);
  930. ::GetWindowText(m_hWnd, rString.GetBufferSetLength(nLen), nLen+1);
  931. rString.ReleaseBuffer();
  932. #ifndef _AFX_NO_OCC_SUPPORT
  933. }
  934. else
  935. {
  936. m_pCtrlSite->GetWindowText(rString);
  937. }
  938. #endif
  939. }
  940. int CWnd::GetDlgItemText(int nID, CString& rString) const
  941. {
  942. ASSERT(::IsWindow(m_hWnd));
  943. rString = &afxChNil; // empty without deallocating
  944. #ifndef _AFX_NO_OCC_SUPPORT
  945. if (m_pCtrlCont == NULL)
  946. {
  947. #endif
  948. HWND hWnd = ::GetDlgItem(m_hWnd, nID);
  949. if (hWnd != NULL)
  950. {
  951. int nLen = ::GetWindowTextLength(hWnd);
  952. ::GetWindowText(hWnd, rString.GetBufferSetLength(nLen), nLen+1);
  953. rString.ReleaseBuffer();
  954. }
  955. #ifndef _AFX_NO_OCC_SUPPORT
  956. }
  957. else
  958. {
  959. CWnd* pWnd = GetDlgItem(nID);
  960. if (pWnd != NULL)
  961. pWnd->GetWindowText(rString);
  962. }
  963. #endif
  964. return rString.GetLength();
  965. }
  966. BOOL CWnd::GetWindowPlacement(WINDOWPLACEMENT* lpwndpl) const
  967. {
  968. ASSERT(::IsWindow(m_hWnd));
  969. lpwndpl->length = sizeof(WINDOWPLACEMENT);
  970. return ::GetWindowPlacement(m_hWnd, lpwndpl);
  971. }
  972. BOOL CWnd::SetWindowPlacement(const WINDOWPLACEMENT* lpwndpl)
  973. {
  974. ASSERT(::IsWindow(m_hWnd));
  975. ((WINDOWPLACEMENT*)lpwndpl)->length = sizeof(WINDOWPLACEMENT);
  976. return ::SetWindowPlacement(m_hWnd, lpwndpl);
  977. }
  978. /////////////////////////////////////////////////////////////////////////////
  979. // CWnd will delegate owner draw messages to self drawing controls
  980. // Drawing: for all 4 control types
  981. void CWnd::OnDrawItem(int /*nIDCtl*/, LPDRAWITEMSTRUCT lpDrawItemStruct)
  982. {
  983. if (lpDrawItemStruct->CtlType == ODT_MENU)
  984. {
  985. CMenu* pMenu = CMenu::FromHandlePermanent(
  986. (HMENU)lpDrawItemStruct->hwndItem);
  987. if (pMenu != NULL)
  988. {
  989. pMenu->DrawItem(lpDrawItemStruct);
  990. return; // eat it
  991. }
  992. }
  993. else
  994. {
  995. // reflect notification to child window control
  996. if (ReflectLastMsg(lpDrawItemStruct->hwndItem))
  997. return; // eat it
  998. }
  999. // not handled - do default
  1000. Default();
  1001. }
  1002. // Drawing: for all 4 control types
  1003. int CWnd::OnCompareItem(int /*nIDCtl*/, LPCOMPAREITEMSTRUCT lpCompareItemStruct)
  1004. {
  1005. // reflect notification to child window control
  1006. LRESULT lResult;
  1007. if (ReflectLastMsg(lpCompareItemStruct->hwndItem, &lResult))
  1008. return (int)lResult; // eat it
  1009. // not handled - do default
  1010. return (int)Default();
  1011. }
  1012. void CWnd::OnDeleteItem(int /*nIDCtl*/, LPDELETEITEMSTRUCT lpDeleteItemStruct)
  1013. {
  1014. // reflect notification to child window control
  1015. if (ReflectLastMsg(lpDeleteItemStruct->hwndItem))
  1016. return; // eat it
  1017. // not handled - do default
  1018. Default();
  1019. }
  1020. int CWnd::OnCharToItem(UINT, CListBox* pWnd, UINT)
  1021. {
  1022. if (pWnd != NULL)
  1023. {
  1024. LRESULT lResult;
  1025. if (pWnd->SendChildNotifyLastMsg(&lResult))
  1026. return (int)lResult; // eat it
  1027. }
  1028. // not handled - do default
  1029. return (int)Default();
  1030. }
  1031. int CWnd::OnVKeyToItem(UINT, CListBox* pWnd, UINT)
  1032. {
  1033. if (pWnd != NULL)
  1034. {
  1035. LRESULT lResult;
  1036. if (pWnd->SendChildNotifyLastMsg(&lResult))
  1037. return (int)lResult; // eat it
  1038. }
  1039. // not handled - do default
  1040. return (int)Default();
  1041. }
  1042. /////////////////////////////////////////////////////////////////////////////
  1043. // Self drawing menus are a little trickier
  1044. BOOL CMenu::TrackPopupMenu(UINT nFlags, int x, int y,
  1045. CWnd* pWnd, LPCRECT lpRect)
  1046. {
  1047. ASSERT(m_hMenu != NULL);
  1048. _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
  1049. HWND hWndOld = pThreadState->m_hTrackingWindow;
  1050. HMENU hMenuOld = pThreadState->m_hTrackingMenu;
  1051. pThreadState->m_hTrackingWindow = pWnd->GetSafeHwnd();
  1052. pThreadState->m_hTrackingMenu = m_hMenu;
  1053. BOOL bOK = ::TrackPopupMenu(m_hMenu, nFlags, x, y, 0,
  1054. pThreadState->m_hTrackingWindow, lpRect);
  1055. pThreadState->m_hTrackingWindow = hWndOld;
  1056. pThreadState->m_hTrackingMenu = hMenuOld;
  1057. return bOK;
  1058. }
  1059. AFX_STATIC CMenu* AFXAPI _AfxFindPopupMenuFromID(CMenu* pMenu, UINT nID)
  1060. {
  1061. ASSERT_VALID(pMenu);
  1062. // walk through all items, looking for ID match
  1063. UINT nItems = pMenu->GetMenuItemCount();
  1064. for (int iItem = 0; iItem < (int)nItems; iItem++)
  1065. {
  1066. CMenu* pPopup = pMenu->GetSubMenu(iItem);
  1067. if (pPopup != NULL)
  1068. {
  1069. // recurse to child popup
  1070. pPopup = _AfxFindPopupMenuFromID(pPopup, nID);
  1071. // check popups on this popup
  1072. if (pPopup != NULL)
  1073. return pPopup;
  1074. }
  1075. else if (pMenu->GetMenuItemID(iItem) == nID)
  1076. {
  1077. // it is a normal item inside our popup
  1078. pMenu = CMenu::FromHandlePermanent(pMenu->m_hMenu);
  1079. return pMenu;
  1080. }
  1081. }
  1082. // not found
  1083. return NULL;
  1084. }
  1085. // Measure item implementation relies on unique control/menu IDs
  1086. void CWnd::OnMeasureItem(int /*nIDCtl*/, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
  1087. {
  1088. if (lpMeasureItemStruct->CtlType == ODT_MENU)
  1089. {
  1090. ASSERT(lpMeasureItemStruct->CtlID == 0);
  1091. CMenu* pMenu;
  1092. _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  1093. if (pThreadState->m_hTrackingWindow == m_hWnd)
  1094. {
  1095. // start from popup
  1096. pMenu = CMenu::FromHandle(pThreadState->m_hTrackingMenu);
  1097. }
  1098. else
  1099. {
  1100. // start from menubar
  1101. pMenu = GetMenu();
  1102. }
  1103. pMenu = _AfxFindPopupMenuFromID(pMenu, lpMeasureItemStruct->itemID);
  1104. if (pMenu != NULL)
  1105. pMenu->MeasureItem(lpMeasureItemStruct);
  1106. else
  1107. TRACE1("Warning: unknown WM_MEASUREITEM for menu item 0x%04X.\n",
  1108. lpMeasureItemStruct->itemID);
  1109. }
  1110. else
  1111. {
  1112. CWnd* pChild = GetDescendantWindow(lpMeasureItemStruct->CtlID, TRUE);
  1113. if (pChild != NULL && pChild->SendChildNotifyLastMsg())
  1114. return; // eaten by child
  1115. }
  1116. // not handled - do default
  1117. Default();
  1118. }
  1119. /////////////////////////////////////////////////////////////////////////////
  1120. // Additional helpers for WNDCLASS init
  1121. // like RegisterClass, except will automatically call UnregisterClass
  1122. BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass)
  1123. {
  1124. WNDCLASS wndcls;
  1125. if (GetClassInfo(lpWndClass->hInstance, lpWndClass->lpszClassName,
  1126. &wndcls))
  1127. {
  1128. // class already registered
  1129. return TRUE;
  1130. }
  1131. if (!::RegisterClass(lpWndClass))
  1132. {
  1133. TRACE1("Can't register window class named %s\n",
  1134. lpWndClass->lpszClassName);
  1135. return FALSE;
  1136. }
  1137. if (afxContextIsDLL)
  1138. {
  1139. AfxLockGlobals(CRIT_REGCLASSLIST);
  1140. TRY
  1141. {
  1142. // class registered successfully, add to registered list
  1143. AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  1144. LPTSTR lpszUnregisterList = pModuleState->m_szUnregisterList;
  1145. // the buffer is of fixed size -- ensure that it does not overflow
  1146. ASSERT(lstrlen(lpszUnregisterList) + 1 +
  1147. lstrlen(lpWndClass->lpszClassName) + 1 <
  1148. _countof(pModuleState->m_szUnregisterList));
  1149. // append classname + newline to m_szUnregisterList
  1150. lstrcat(lpszUnregisterList, lpWndClass->lpszClassName);
  1151. TCHAR szTemp[2];
  1152. szTemp[0] = '\n';
  1153. szTemp[1] = '\0';
  1154. lstrcat(lpszUnregisterList, szTemp);
  1155. }
  1156. CATCH_ALL(e)
  1157. {
  1158. AfxUnlockGlobals(CRIT_REGCLASSLIST);
  1159. THROW_LAST();
  1160. // Note: DELETE_EXCEPTION not required.
  1161. }
  1162. END_CATCH_ALL
  1163. AfxUnlockGlobals(CRIT_REGCLASSLIST);
  1164. }
  1165. return TRUE;
  1166. }
  1167. LPCTSTR AFXAPI AfxRegisterWndClass(UINT nClassStyle,
  1168. HCURSOR hCursor, HBRUSH hbrBackground, HICON hIcon)
  1169. {
  1170. // Returns a temporary string name for the class
  1171. // Save in a CString if you want to use it for a long time
  1172. LPTSTR lpszName = AfxGetThreadState()->m_szTempClassName;
  1173. // generate a synthetic name for this class
  1174. HINSTANCE hInst = AfxGetInstanceHandle();
  1175. if (hCursor == NULL && hbrBackground == NULL && hIcon == NULL)
  1176. wsprintf(lpszName, _T("Afx:%x:%x"), (UINT)hInst, nClassStyle);
  1177. else
  1178. wsprintf(lpszName, _T("Afx:%x:%x:%x:%x:%x"), (UINT)hInst, nClassStyle,
  1179. (UINT)hCursor, (UINT)hbrBackground, (UINT)hIcon);
  1180. // see if the class already exists
  1181. WNDCLASS wndcls;
  1182. if (::GetClassInfo(hInst, lpszName, &wndcls))
  1183. {
  1184. // already registered, assert everything is good
  1185. ASSERT(wndcls.style == nClassStyle);
  1186. // NOTE: We have to trust that the hIcon, hbrBackground, and the
  1187. // hCursor are semantically the same, because sometimes Windows does
  1188. // some internal translation or copying of those handles before
  1189. // storing them in the internal WNDCLASS retrieved by GetClassInfo.
  1190. return lpszName;
  1191. }
  1192. // otherwise we need to register a new class
  1193. wndcls.style = nClassStyle;
  1194. wndcls.lpfnWndProc = DefWindowProc;
  1195. wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
  1196. wndcls.hInstance = hInst;
  1197. wndcls.hIcon = hIcon;
  1198. wndcls.hCursor = hCursor;
  1199. wndcls.hbrBackground = hbrBackground;
  1200. wndcls.lpszMenuName = NULL;
  1201. wndcls.lpszClassName = lpszName;
  1202. if (!AfxRegisterClass(&wndcls))
  1203. AfxThrowResourceException();
  1204. // return thread-local pointer
  1205. return lpszName;
  1206. }
  1207. struct AFX_CTLCOLOR
  1208. {
  1209. HWND hWnd;
  1210. HDC hDC;
  1211. UINT nCtlType;
  1212. };
  1213. LRESULT CWnd::OnNTCtlColor(WPARAM wParam, LPARAM lParam)
  1214. {
  1215. // fill in special struct for compatiblity with 16-bit WM_CTLCOLOR
  1216. AFX_CTLCOLOR ctl;
  1217. ctl.hDC = (HDC)wParam;
  1218. ctl.hWnd = (HWND)lParam;
  1219. _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  1220. ctl.nCtlType = pThreadState->m_lastSentMsg.message - WM_CTLCOLORMSGBOX;
  1221. ASSERT(ctl.nCtlType >= CTLCOLOR_MSGBOX);
  1222. ASSERT(ctl.nCtlType <= CTLCOLOR_STATIC);
  1223. // Note: We call the virtual WindowProc for this window directly,
  1224. // instead of calling AfxCallWindowProc, so that Default()
  1225. // will still work (it will call the Default window proc with
  1226. // the original Win32 WM_CTLCOLOR message).
  1227. return WindowProc(WM_CTLCOLOR, 0, (LPARAM)&ctl);
  1228. }
  1229. /////////////////////////////////////////////////////////////////////////////
  1230. // CWnd extensions for help support
  1231. void CWnd::WinHelp(DWORD dwData, UINT nCmd)
  1232. {
  1233. CWinApp* pApp = AfxGetApp();
  1234. ASSERT_VALID(pApp);
  1235. ASSERT(pApp->m_pszHelpFilePath != NULL);
  1236. CWaitCursor wait;
  1237. if (IsFrameWnd())
  1238. {
  1239. // CFrameWnd windows should be allowed to exit help mode first
  1240. CFrameWnd* pFrameWnd = (CFrameWnd*)this;
  1241. pFrameWnd->ExitHelpMode();
  1242. }
  1243. // cancel any tracking modes
  1244. SendMessage(WM_CANCELMODE);
  1245. SendMessageToDescendants(WM_CANCELMODE, 0, 0, TRUE, TRUE);
  1246. // need to use top level parent (for the case where m_hWnd is in DLL)
  1247. CWnd* pWnd = GetTopLevelParent();
  1248. pWnd->SendMessage(WM_CANCELMODE);
  1249. pWnd->SendMessageToDescendants(WM_CANCELMODE, 0, 0, TRUE, TRUE);
  1250. // attempt to cancel capture
  1251. HWND hWndCapture = ::GetCapture();
  1252. if (hWndCapture != NULL)
  1253. ::SendMessage(hWndCapture, WM_CANCELMODE, 0, 0);
  1254. TRACE3("WinHelp: pszHelpFile = '%s', dwData: $%lx, fuCommand: %d.\n",
  1255. pApp->m_pszHelpFilePath, dwData, nCmd);
  1256. // finally, run the Windows Help engine
  1257. if (!::WinHelp(pWnd->m_hWnd, pApp->m_pszHelpFilePath, nCmd, dwData))
  1258. AfxMessageBox(AFX_IDP_FAILED_TO_LAUNCH_HELP);
  1259. }
  1260. /////////////////////////////////////////////////////////////////////////////
  1261. // Message table implementation
  1262. BEGIN_MESSAGE_MAP(CWnd, CCmdTarget)
  1263. ON_MESSAGE(WM_CTLCOLORSTATIC, OnNTCtlColor)
  1264. ON_MESSAGE(WM_CTLCOLOREDIT, OnNTCtlColor)
  1265. ON_MESSAGE(WM_CTLCOLORBTN, OnNTCtlColor)
  1266. ON_MESSAGE(WM_CTLCOLORLISTBOX, OnNTCtlColor)
  1267. ON_MESSAGE(WM_CTLCOLORDLG, OnNTCtlColor)
  1268. ON_MESSAGE(WM_CTLCOLORMSGBOX, OnNTCtlColor)
  1269. ON_MESSAGE(WM_CTLCOLORSCROLLBAR, OnNTCtlColor)
  1270. //{{AFX_MSG_MAP(CWnd)
  1271. ON_WM_DRAWITEM()
  1272. ON_WM_MEASUREITEM()
  1273. ON_WM_CTLCOLOR()
  1274. ON_WM_COMPAREITEM()
  1275. ON_WM_ENTERIDLE()
  1276. ON_WM_HSCROLL()
  1277. ON_WM_VSCROLL()
  1278. ON_WM_DELETEITEM()
  1279. ON_WM_CHARTOITEM()
  1280. ON_WM_VKEYTOITEM()
  1281. ON_WM_NCDESTROY()
  1282. ON_WM_PARENTNOTIFY()
  1283. ON_WM_SYSCOLORCHANGE()
  1284. ON_WM_DEVMODECHANGE()
  1285. ON_WM_HELPINFO()
  1286. ON_WM_SETTINGCHANGE()
  1287. //}}AFX_MSG_MAP
  1288. #ifndef _AFX_NO_OCC_SUPPORT
  1289. ON_WM_DESTROY()
  1290. #endif
  1291. ON_MESSAGE(WM_ACTIVATETOPLEVEL, OnActivateTopLevel)
  1292. ON_MESSAGE(WM_DISPLAYCHANGE, OnDisplayChange)
  1293. ON_REGISTERED_MESSAGE(CWnd::m_nMsgDragList, OnDragList)
  1294. END_MESSAGE_MAP()
  1295. /////////////////////////////////////////////////////////////////////////////
  1296. // Routines for fast search of message maps
  1297. const AFX_MSGMAP_ENTRY* AFXAPI
  1298. AfxFindMessageEntry(const AFX_MSGMAP_ENTRY* lpEntry,
  1299. UINT nMsg, UINT nCode, UINT nID)
  1300. {
  1301. #if defined(_M_IX86) && !defined(_AFX_PORTABLE)
  1302. // 32-bit Intel 386/486 version.
  1303. ASSERT(offsetof(AFX_MSGMAP_ENTRY, nMessage) == 0);
  1304. ASSERT(offsetof(AFX_MSGMAP_ENTRY, nCode) == 4);
  1305. ASSERT(offsetof(AFX_MSGMAP_ENTRY, nID) == 8);
  1306. ASSERT(offsetof(AFX_MSGMAP_ENTRY, nLastID) == 12);
  1307. ASSERT(offsetof(AFX_MSGMAP_ENTRY, nSig) == 16);
  1308. _asm
  1309. {
  1310. MOV EBX,lpEntry
  1311. MOV EAX,nMsg
  1312. MOV EDX,nCode
  1313. MOV ECX,nID
  1314. __loop:
  1315. CMP DWORD PTR [EBX+16],0 ; nSig (0 => end)
  1316. JZ __failed
  1317. CMP EAX,DWORD PTR [EBX] ; nMessage
  1318. JE __found_message
  1319. __next:
  1320. ADD EBX,SIZE AFX_MSGMAP_ENTRY
  1321. JMP short __loop
  1322. __found_message:
  1323. CMP EDX,DWORD PTR [EBX+4] ; nCode
  1324. JNE __next
  1325. // message and code good so far
  1326. // check the ID
  1327. CMP ECX,DWORD PTR [EBX+8] ; nID
  1328. JB __next
  1329. CMP ECX,DWORD PTR [EBX+12] ; nLastID
  1330. JA __next
  1331. // found a match
  1332. MOV lpEntry,EBX ; return EBX
  1333. JMP short __end
  1334. __failed:
  1335. XOR EAX,EAX ; return NULL
  1336. MOV lpEntry,EAX
  1337. __end:
  1338. }
  1339. return lpEntry;
  1340. #else // _AFX_PORTABLE
  1341. // C version of search routine
  1342. while (lpEntry->nSig != AfxSig_end)
  1343. {
  1344. if (lpEntry->nMessage == nMsg && lpEntry->nCode == nCode &&
  1345. nID >= lpEntry->nID && nID <= lpEntry->nLastID)
  1346. {
  1347. return lpEntry;
  1348. }
  1349. lpEntry++;
  1350. }
  1351. return NULL; // not found
  1352. #endif // _AFX_PORTABLE
  1353. }
  1354. /////////////////////////////////////////////////////////////////////////////
  1355. // Cache of most recently sent messages
  1356. #ifndef iHashMax
  1357. // iHashMax must be a power of two
  1358. #define iHashMax 512
  1359. #endif
  1360. struct AFX_MSG_CACHE
  1361. {
  1362. UINT nMsg;
  1363. const AFX_MSGMAP_ENTRY* lpEntry;
  1364. const AFX_MSGMAP* pMessageMap;
  1365. };
  1366. AFX_MSG_CACHE _afxMsgCache[iHashMax];
  1367. void AFXAPI AfxResetMsgCache()
  1368. {
  1369. memset(_afxMsgCache, 0, sizeof(_afxMsgCache));
  1370. }
  1371. /////////////////////////////////////////////////////////////////////////////
  1372. // main WindowProc implementation
  1373. LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
  1374. {
  1375. // OnWndMsg does most of the work, except for DefWindowProc call
  1376. LRESULT lResult = 0;
  1377. if (!OnWndMsg(message, wParam, lParam, &lResult))
  1378. lResult = DefWindowProc(message, wParam, lParam);
  1379. return lResult;
  1380. }
  1381. BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
  1382. {
  1383. LRESULT lResult = 0;
  1384. // special case for commands
  1385. if (message == WM_COMMAND)
  1386. {
  1387. if (OnCommand(wParam, lParam))
  1388. {
  1389. lResult = 1;
  1390. goto LReturnTrue;
  1391. }
  1392. return FALSE;
  1393. }
  1394. // special case for notifies
  1395. if (message == WM_NOTIFY)
  1396. {
  1397. NMHDR* pNMHDR = (NMHDR*)lParam;
  1398. if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))
  1399. goto LReturnTrue;
  1400. return FALSE;
  1401. }
  1402. // special case for activation
  1403. if (message == WM_ACTIVATE)
  1404. _AfxHandleActivate(this, wParam, CWnd::FromHandle((HWND)lParam));
  1405. // special case for set cursor HTERROR
  1406. if (message == WM_SETCURSOR &&
  1407. _AfxHandleSetCursor(this, (short)LOWORD(lParam), HIWORD(lParam)))
  1408. {
  1409. lResult = 1;
  1410. goto LReturnTrue;
  1411. }
  1412. const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap();
  1413. UINT iHash; iHash = (LOWORD((DWORD)pMessageMap) ^ message) & (iHashMax-1);
  1414. AfxLockGlobals(CRIT_WINMSGCACHE);
  1415. AFX_MSG_CACHE* pMsgCache; pMsgCache = &_afxMsgCache[iHash];
  1416. const AFX_MSGMAP_ENTRY* lpEntry;
  1417. if (message == pMsgCache->nMsg && pMessageMap == pMsgCache->pMessageMap)
  1418. {
  1419. // cache hit
  1420. lpEntry = pMsgCache->lpEntry;
  1421. AfxUnlockGlobals(CRIT_WINMSGCACHE);
  1422. if (lpEntry == NULL)
  1423. return FALSE;
  1424. // cache hit, and it needs to be handled
  1425. if (message < 0xC000)
  1426. goto LDispatch;
  1427. else
  1428. goto LDispatchRegistered;
  1429. }
  1430. else
  1431. {
  1432. // not in cache, look for it
  1433. pMsgCache->nMsg = message;
  1434. pMsgCache->pMessageMap = pMessageMap;
  1435. #ifdef _AFXDLL
  1436. for (/* pMessageMap already init'ed */; pMessageMap != NULL;
  1437. pMessageMap = (*pMessageMap->pfnGetBaseMap)())
  1438. #else
  1439. for (/* pMessageMap already init'ed */; pMessageMap != NULL;
  1440. pMessageMap = pMessageMap->pBaseMap)
  1441. #endif
  1442. {
  1443. // Note: catch not so common but fatal mistake!!
  1444. // BEGIN_MESSAGE_MAP(CMyWnd, CMyWnd)
  1445. #ifdef _AFXDLL
  1446. ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)());
  1447. #else
  1448. ASSERT(pMessageMap != pMessageMap->pBaseMap);
  1449. #endif
  1450. if (message < 0xC000)
  1451. {
  1452. // constant window message
  1453. if ((lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries,
  1454. message, 0, 0)) != NULL)
  1455. {
  1456. pMsgCache->lpEntry = lpEntry;
  1457. AfxUnlockGlobals(CRIT_WINMSGCACHE);
  1458. goto LDispatch;
  1459. }
  1460. }
  1461. else
  1462. {
  1463. // registered windows message
  1464. lpEntry = pMessageMap->lpEntries;
  1465. while ((lpEntry = AfxFindMessageEntry(lpEntry, 0xC000, 0, 0)) != NULL)
  1466. {
  1467. UINT* pnID = (UINT*)(lpEntry->nSig);
  1468. ASSERT(*pnID >= 0xC000 || *pnID == 0);
  1469. // must be successfully registered
  1470. if (*pnID == message)
  1471. {
  1472. pMsgCache->lpEntry = lpEntry;
  1473. AfxUnlockGlobals(CRIT_WINMSGCACHE);
  1474. goto LDispatchRegistered;
  1475. }
  1476. lpEntry++; // keep looking past this one
  1477. }
  1478. }
  1479. }
  1480. pMsgCache->lpEntry = NULL;
  1481. AfxUnlockGlobals(CRIT_WINMSGCACHE);
  1482. return FALSE;
  1483. }
  1484. ASSERT(FALSE); // not reached
  1485. LDispatch:
  1486. ASSERT(message < 0xC000);
  1487. union MessageMapFunctions mmf;
  1488. mmf.pfn = lpEntry->pfn;
  1489. // if we've got WM_SETTINGCHANGE / WM_WININICHANGE, we need to
  1490. // decide if we're going to call OnWinIniChange() or OnSettingChange()
  1491. int nSig;
  1492. nSig = lpEntry->nSig;
  1493. if (lpEntry->nID == WM_SETTINGCHANGE)
  1494. {
  1495. DWORD dwVersion = GetVersion();
  1496. if (LOBYTE(LOWORD(dwVersion)) >= 4)
  1497. nSig = AfxSig_vws;
  1498. else
  1499. nSig = AfxSig_vs;
  1500. }
  1501. switch (nSig)
  1502. {
  1503. default:
  1504. ASSERT(FALSE);
  1505. break;
  1506. case AfxSig_bD:
  1507. lResult = (this->*mmf.pfn_bD)(CDC::FromHandle((HDC)wParam));
  1508. break;
  1509. case AfxSig_bb: // AfxSig_bb, AfxSig_bw, AfxSig_bh
  1510. lResult = (this->*mmf.pfn_bb)((BOOL)wParam);
  1511. break;
  1512. case AfxSig_bWww: // really AfxSig_bWiw
  1513. lResult = (this->*mmf.pfn_bWww)(CWnd::FromHandle((HWND)wParam),
  1514. (short)LOWORD(lParam), HIWORD(lParam));
  1515. break;
  1516. case AfxSig_bWCDS:
  1517. lResult = (this->*mmf.pfn_bWCDS)(CWnd::FromHandle((HWND)wParam),
  1518. (COPYDATASTRUCT*)lParam);
  1519. break;
  1520. case AfxSig_bHELPINFO:
  1521. lResult = (this->*mmf.pfn_bHELPINFO)((HELPINFO*)lParam);
  1522. break;
  1523. case AfxSig_hDWw:
  1524. {
  1525. // special case for OnCtlColor to avoid too many temporary objects
  1526. ASSERT(message == WM_CTLCOLOR);
  1527. AFX_CTLCOLOR* pCtl = (AFX_CTLCOLOR*)lParam;
  1528. CDC dcTemp; dcTemp.m_hDC = pCtl->hDC;
  1529. CWnd wndTemp; wndTemp.m_hWnd = pCtl->hWnd;
  1530. UINT nCtlType = pCtl->nCtlType;
  1531. // if not coming from a permanent window, use stack temporary
  1532. CWnd* pWnd = CWnd::FromHandlePermanent(wndTemp.m_hWnd);
  1533. if (pWnd == NULL)
  1534. {
  1535. #ifndef _AFX_NO_OCC_SUPPORT
  1536. // determine the site of the OLE control if it is one
  1537. COleControlSite* pSite;
  1538. if (m_pCtrlCont != NULL && (pSite = (COleControlSite*)
  1539. m_pCtrlCont->m_siteMap.GetValueAt(wndTemp.m_hWnd)) != NULL)
  1540. {
  1541. wndTemp.m_pCtrlSite = pSite;
  1542. }
  1543. #endif
  1544. pWnd = &wndTemp;
  1545. }
  1546. HBRUSH hbr = (this->*mmf.pfn_hDWw)(&dcTemp, pWnd, nCtlType);
  1547. // fast detach of temporary objects
  1548. dcTemp.m_hDC = NULL;
  1549. wndTemp.m_hWnd = NULL;
  1550. lResult = (LRESULT)hbr;
  1551. }
  1552. break;
  1553. case AfxSig_hDw:
  1554. {
  1555. // special case for CtlColor to avoid too many temporary objects
  1556. ASSERT(message == WM_REFLECT_BASE+WM_CTLCOLOR);
  1557. AFX_CTLCOLOR* pCtl = (AFX_CTLCOLOR*)lParam;
  1558. CDC dcTemp; dcTemp.m_hDC = pCtl->hDC;
  1559. UINT nCtlType = pCtl->nCtlType;
  1560. HBRUSH hbr = (this->*mmf.pfn_hDw)(&dcTemp, nCtlType);
  1561. // fast detach of temporary objects
  1562. dcTemp.m_hDC = NULL;
  1563. lResult = (LRESULT)hbr;
  1564. }
  1565. break;
  1566. case AfxSig_iwWw:
  1567. lResult = (this->*mmf.pfn_iwWw)(LOWORD(wParam),
  1568. CWnd::FromHandle((HWND)lParam), HIWORD(wParam));
  1569. break;
  1570. case AfxSig_iww:
  1571. lResult = (this->*mmf.pfn_iww)(LOWORD(wParam), HIWORD(wParam));
  1572. break;
  1573. case AfxSig_iWww: // really AfxSig_iWiw
  1574. lResult = (this->*mmf.pfn_iWww)(CWnd::FromHandle((HWND)wParam),
  1575. (short)LOWORD(lParam), HIWORD(lParam));
  1576. break;
  1577. case AfxSig_is:
  1578. lResult = (this->*mmf.pfn_is)((LPTSTR)lParam);
  1579. break;
  1580. case AfxSig_lwl:
  1581. lResult = (this->*mmf.pfn_lwl)(wParam, lParam);
  1582. break;
  1583. case AfxSig_lwwM:
  1584. lResult = (this->*mmf.pfn_lwwM)((UINT)LOWORD(wParam),
  1585. (UINT)HIWORD(wParam), (CMenu*)CMenu::FromHandle((HMENU)lParam));
  1586. break;
  1587. case AfxSig_vv:
  1588. (this->*mmf.pfn_vv)();
  1589. break;
  1590. case AfxSig_vw: // AfxSig_vb, AfxSig_vh
  1591. (this->*mmf.pfn_vw)(wParam);
  1592. break;
  1593. case AfxSig_vww:
  1594. (this->*mmf.pfn_vww)((UINT)wParam, (UINT)lParam);
  1595. break;
  1596. case AfxSig_vvii:
  1597. (this->*mmf.pfn_vvii)((short)LOWORD(lParam), (short)HIWORD(lParam));
  1598. break;
  1599. case AfxSig_vwww:
  1600. (this->*mmf.pfn_vwww)(wParam, LOWORD(lParam), HIWORD(lParam));
  1601. break;
  1602. case AfxSig_vwii:
  1603. (this->*mmf.pfn_vwii)(wParam, LOWORD(lParam), HIWORD(lParam));
  1604. break;
  1605. case AfxSig_vwl:
  1606. (this->*mmf.pfn_vwl)(wParam, lParam);
  1607. break;
  1608. case AfxSig_vbWW:
  1609. (this->*mmf.pfn_vbWW)(m_hWnd == (HWND)lParam,
  1610. CWnd::FromHandle((HWND)lParam),
  1611. CWnd::FromHandle((HWND)wParam));
  1612. break;
  1613. case AfxSig_vD:
  1614. (this->*mmf.pfn_vD)(CDC::FromHandle((HDC)wParam));
  1615. break;
  1616. case AfxSig_vM:
  1617. (this->*mmf.pfn_vM)(CMenu::FromHandle((HMENU)wParam));
  1618. break;
  1619. case AfxSig_vMwb:
  1620. (this->*mmf.pfn_vMwb)(CMenu::FromHandle((HMENU)wParam),
  1621. LOWORD(lParam), (BOOL)HIWORD(lParam));
  1622. break;
  1623. case AfxSig_vW:
  1624. (this->*mmf.pfn_vW)(CWnd::FromHandle((HWND)wParam));
  1625. break;
  1626. case AfxSig_vW2:
  1627. (this->*mmf.pfn_vW)(CWnd::FromHandle((HWND)lParam));
  1628. break;
  1629. case AfxSig_vWww:
  1630. (this->*mmf.pfn_vWww)(CWnd::FromHandle((HWND)wParam), LOWORD(lParam),
  1631. HIWORD(lParam));
  1632. break;
  1633. case AfxSig_vWp:
  1634. {
  1635. CPoint point((DWORD)lParam);
  1636. (this->*mmf.pfn_vWp)(CWnd::FromHandle((HWND)wParam), point);
  1637. }
  1638. break;
  1639. case AfxSig_vWh:
  1640. (this->*mmf.pfn_vWh)(CWnd::FromHandle((HWND)wParam),
  1641. (HANDLE)lParam);
  1642. break;
  1643. case AfxSig_vwW:
  1644. (this->*mmf.pfn_vwW)(wParam, CWnd::FromHandle((HWND)lParam));
  1645. break;
  1646. case AfxSig_vwWb:
  1647. (this->*mmf.pfn_vwWb)((UINT)(LOWORD(wParam)),
  1648. CWnd::FromHandle((HWND)lParam), (BOOL)HIWORD(wParam));
  1649. break;
  1650. case AfxSig_vwwW:
  1651. case AfxSig_vwwx:
  1652. {
  1653. // special case for WM_VSCROLL and WM_HSCROLL
  1654. ASSERT(message == WM_VSCROLL || message == WM_HSCROLL ||
  1655. message == WM_VSCROLL+WM_REFLECT_BASE || message == WM_HSCROLL+WM_REFLECT_BASE);
  1656. int nScrollCode = (short)LOWORD(wParam);
  1657. int nPos = (short)HIWORD(wParam);
  1658. if (lpEntry->nSig == AfxSig_vwwW)
  1659. (this->*mmf.pfn_vwwW)(nScrollCode, nPos,
  1660. CWnd::FromHandle((HWND)lParam));
  1661. else
  1662. (this->*mmf.pfn_vwwx)(nScrollCode, nPos);
  1663. }
  1664. break;
  1665. case AfxSig_vs:
  1666. (this->*mmf.pfn_vs)((LPTSTR)lParam);
  1667. break;
  1668. case AfxSig_vws:
  1669. (this->*mmf.pfn_vws)((UINT) wParam, (LPCTSTR)lParam);
  1670. break;
  1671. case AfxSig_vOWNER:
  1672. (this->*mmf.pfn_vOWNER)((int)wParam, (LPTSTR)lParam);
  1673. lResult = TRUE;
  1674. break;
  1675. case AfxSig_iis:
  1676. lResult = (this->*mmf.pfn_iis)((int)wParam, (LPTSTR)lParam);
  1677. break;
  1678. case AfxSig_wp:
  1679. {
  1680. CPoint point((DWORD)lParam);
  1681. lResult = (this->*mmf.pfn_wp)(point);
  1682. }
  1683. break;
  1684. case AfxSig_wv: // AfxSig_bv, AfxSig_wv
  1685. lResult = (this->*mmf.pfn_wv)();
  1686. break;
  1687. case AfxSig_vCALC:
  1688. (this->*mmf.pfn_vCALC)((BOOL)wParam, (NCCALCSIZE_PARAMS*)lParam);
  1689. break;
  1690. case AfxSig_vPOS:
  1691. (this->*mmf.pfn_vPOS)((WINDOWPOS*)lParam);
  1692. break;
  1693. case AfxSig_vwwh:
  1694. (this->*mmf.pfn_vwwh)(LOWORD(wParam), HIWORD(wParam), (HANDLE)lParam);
  1695. break;
  1696. case AfxSig_vwp:
  1697. {
  1698. CPoint point((DWORD)lParam);
  1699. (this->*mmf.pfn_vwp)(wParam, point);
  1700. break;
  1701. }
  1702. case AfxSig_vwSIZING:
  1703. (this->*mmf.pfn_vwl)(wParam, lParam);
  1704. lResult = TRUE;
  1705. break;
  1706. case AfxSig_bwsp:
  1707. lResult = (this->*mmf.pfn_bwsp)(LOWORD(wParam), (short) HIWORD(wParam),
  1708. CPoint(LOWORD(lParam), HIWORD(lParam)));
  1709. if (!lResult)
  1710. return FALSE;
  1711. }
  1712. goto LReturnTrue;
  1713. LDispatchRegistered: // for registered windows messages
  1714. ASSERT(message >= 0xC000);
  1715. mmf.pfn = lpEntry->pfn;
  1716. lResult = (this->*mmf.pfn_lwl)(wParam, lParam);
  1717. LReturnTrue:
  1718. if (pResult != NULL)
  1719. *pResult = lResult;
  1720. return TRUE;
  1721. }
  1722. /////////////////////////////////////////////////////////////////////////////
  1723. // CTestCmdUI - used to test for disabled commands before dispatching
  1724. class CTestCmdUI : public CCmdUI
  1725. {
  1726. public:
  1727. CTestCmdUI();
  1728. public: // re-implementations only
  1729. virtual void Enable(BOOL bOn);
  1730. virtual void SetCheck(int nCheck);
  1731. virtual void SetRadio(BOOL bOn);
  1732. virtual void SetText(LPCTSTR);
  1733. BOOL m_bEnabled;
  1734. };
  1735. CTestCmdUI::CTestCmdUI()
  1736. {
  1737. m_bEnabled = TRUE; // assume it is enabled
  1738. }
  1739. void CTestCmdUI::Enable(BOOL bOn)
  1740. {
  1741. m_bEnabled = bOn;
  1742. m_bEnableChanged = TRUE;
  1743. }
  1744. void CTestCmdUI::SetCheck(int)
  1745. {
  1746. // do nothing -- just want to know about calls to Enable
  1747. }
  1748. void CTestCmdUI::SetRadio(BOOL)
  1749. {
  1750. // do nothing -- just want to know about calls to Enable
  1751. }
  1752. void CTestCmdUI::SetText(LPCTSTR)
  1753. {
  1754. // do nothing -- just want to know about calls to Enable
  1755. }
  1756. /////////////////////////////////////////////////////////////////////////////
  1757. // CWnd command handling
  1758. BOOL CWnd::OnCommand(WPARAM wParam, LPARAM lParam)
  1759. // return TRUE if command invocation was attempted
  1760. {
  1761. UINT nID = LOWORD(wParam);
  1762. HWND hWndCtrl = (HWND)lParam;
  1763. int nCode = HIWORD(wParam);
  1764. // default routing for command messages (through closure table)
  1765. if (hWndCtrl == NULL)
  1766. {
  1767. // zero IDs for normal commands are not allowed
  1768. if (nID == 0)
  1769. return FALSE;
  1770. // make sure command has not become disabled before routing
  1771. CTestCmdUI state;
  1772. state.m_nID = nID;
  1773. OnCmdMsg(nID, CN_UPDATE_COMMAND_UI, &state, NULL);
  1774. if (!state.m_bEnabled)
  1775. {
  1776. TRACE1("Warning: not executing disabled command %d\n", nID);
  1777. return TRUE;
  1778. }
  1779. // menu or accelerator
  1780. nCode = CN_COMMAND;
  1781. }
  1782. else
  1783. {
  1784. // control notification
  1785. ASSERT(nID == 0 || ::IsWindow(hWndCtrl));
  1786. if (_afxThreadState->m_hLockoutNotifyWindow == m_hWnd)
  1787. return TRUE; // locked out - ignore control notification
  1788. // reflect notification to child window control
  1789. if (ReflectLastMsg(hWndCtrl))
  1790. return TRUE; // eaten by child
  1791. // zero IDs for normal commands are not allowed
  1792. if (nID == 0)
  1793. return FALSE;
  1794. }
  1795. #ifdef _DEBUG
  1796. if (nCode < 0 && nCode != (int)0x8000)
  1797. TRACE1("Implementation Warning: control notification = $%X.\n",
  1798. nCode);
  1799. #endif
  1800. return OnCmdMsg(nID, nCode, NULL, NULL);
  1801. }
  1802. BOOL CWnd::OnNotify(WPARAM, LPARAM lParam, LRESULT* pResult)
  1803. {
  1804. ASSERT(pResult != NULL);
  1805. NMHDR* pNMHDR = (NMHDR*)lParam;
  1806. HWND hWndCtrl = pNMHDR->hwndFrom;
  1807. // get the child ID from the window itself
  1808. UINT nID = _AfxGetDlgCtrlID(hWndCtrl);
  1809. int nCode = pNMHDR->code;
  1810. ASSERT(hWndCtrl != NULL);
  1811. ASSERT(::IsWindow(hWndCtrl));
  1812. if (_afxThreadState->m_hLockoutNotifyWindow == m_hWnd)
  1813. return TRUE; // locked out - ignore control notification
  1814. // reflect notification to child window control
  1815. if (ReflectLastMsg(hWndCtrl, pResult))
  1816. return TRUE; // eaten by child
  1817. AFX_NOTIFY notify;
  1818. notify.pResult = pResult;
  1819. notify.pNMHDR = pNMHDR;
  1820. return OnCmdMsg(nID, MAKELONG(nCode, WM_NOTIFY), &notify, NULL);
  1821. }
  1822. /////////////////////////////////////////////////////////////////////////////
  1823. // CWnd extensions
  1824. CFrameWnd* CWnd::GetParentFrame() const
  1825. {
  1826. if (GetSafeHwnd() == NULL) // no Window attached
  1827. return NULL;
  1828. ASSERT_VALID(this);
  1829. CWnd* pParentWnd = GetParent(); // start with one parent up
  1830. while (pParentWnd != NULL)
  1831. {
  1832. if (pParentWnd->IsFrameWnd())
  1833. return (CFrameWnd*)pParentWnd;
  1834. pParentWnd = pParentWnd->GetParent();
  1835. }
  1836. return NULL;
  1837. }
  1838. HWND AFXAPI AfxGetParentOwner(HWND hWnd)
  1839. {
  1840. // check for permanent-owned window first
  1841. CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
  1842. if (pWnd != NULL)
  1843. return pWnd->GetOwner()->GetSafeHwnd();
  1844. // otherwise, return parent in the Windows sense
  1845. return (::GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) ?
  1846. ::GetParent(hWnd) : ::GetWindow(hWnd, GW_OWNER);
  1847. }
  1848. CWnd* CWnd::GetTopLevelParent() const
  1849. {
  1850. if (GetSafeHwnd() == NULL) // no Window attached
  1851. return NULL;
  1852. ASSERT_VALID(this);
  1853. HWND hWndParent = m_hWnd;
  1854. HWND hWndT;
  1855. while ((hWndT = AfxGetParentOwner(hWndParent)) != NULL)
  1856. hWndParent = hWndT;
  1857. return CWnd::FromHandle(hWndParent);
  1858. }
  1859. CWnd* CWnd::GetTopLevelOwner() const
  1860. {
  1861. if (GetSafeHwnd() == NULL) // no Window attached
  1862. return NULL;
  1863. ASSERT_VALID(this);
  1864. HWND hWndOwner = m_hWnd;
  1865. HWND hWndT;
  1866. while ((hWndT = ::GetWindow(hWndOwner, GW_OWNER)) != NULL)
  1867. hWndOwner = hWndT;
  1868. return CWnd::FromHandle(hWndOwner);
  1869. }
  1870. CWnd* CWnd::GetParentOwner() const
  1871. {
  1872. if (GetSafeHwnd() == NULL) // no Window attached
  1873. return NULL;
  1874. ASSERT_VALID(this);
  1875. HWND hWndParent = m_hWnd;
  1876. HWND hWndT;
  1877. while ((::GetWindowLong(hWndParent, GWL_STYLE) & WS_CHILD) &&
  1878. (hWndT = ::GetParent(hWndParent)) != NULL)
  1879. {
  1880. hWndParent = hWndT;
  1881. }
  1882. return CWnd::FromHandle(hWndParent);
  1883. }
  1884. BOOL CWnd::IsTopParentActive() const
  1885. {
  1886. ASSERT(m_hWnd != NULL);
  1887. ASSERT_VALID(this);
  1888. return CWnd::GetForegroundWindow() ==
  1889. GetTopLevelParent()->GetLastActivePopup();
  1890. }
  1891. void CWnd::ActivateTopParent()
  1892. {
  1893. // special activate logic for floating toolbars and palettes
  1894. CWnd* pTopLevel = GetTopLevelParent();
  1895. CWnd* pActiveWnd = GetForegroundWindow();
  1896. if (pActiveWnd == NULL ||
  1897. !(pActiveWnd->m_hWnd == m_hWnd || ::IsChild(pActiveWnd->m_hWnd, m_hWnd)))
  1898. {
  1899. // clicking on floating frame when it does not have
  1900. // focus itself -- activate the toplevel frame instead.
  1901. pTopLevel->SetForegroundWindow();
  1902. }
  1903. }
  1904. CFrameWnd* CWnd::GetTopLevelFrame() const
  1905. {
  1906. if (GetSafeHwnd() == NULL) // no Window attached
  1907. return NULL;
  1908. ASSERT_VALID(this);
  1909. CFrameWnd* pFrameWnd = (CFrameWnd*)this;
  1910. if (!IsFrameWnd())
  1911. pFrameWnd = GetParentFrame();
  1912. if (pFrameWnd != NULL)
  1913. {
  1914. CFrameWnd* pTemp;
  1915. while ((pTemp = pFrameWnd->GetParentFrame()) != NULL)
  1916. pFrameWnd = pTemp;
  1917. }
  1918. return pFrameWnd;
  1919. }
  1920. CWnd* PASCAL CWnd::GetSafeOwner(CWnd* pParent, HWND* pWndTop)
  1921. {
  1922. HWND hWnd = GetSafeOwner_(pParent->GetSafeHwnd(), pWndTop);
  1923. return CWnd::FromHandle(hWnd);
  1924. }
  1925. int CWnd::MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption, UINT nType)
  1926. {
  1927. if (lpszCaption == NULL)
  1928. lpszCaption = AfxGetAppName();
  1929. int nResult = ::MessageBox(GetSafeHwnd(), lpszText, lpszCaption, nType);
  1930. return nResult;
  1931. }
  1932. CWnd* PASCAL CWnd::GetDescendantWindow(HWND hWnd, int nID, BOOL bOnlyPerm)
  1933. {
  1934. // GetDlgItem recursive (return first found)
  1935. // breadth-first for 1 level, then depth-first for next level
  1936. // use GetDlgItem since it is a fast USER function
  1937. HWND hWndChild;
  1938. CWnd* pWndChild;
  1939. if ((hWndChild = ::GetDlgItem(hWnd, nID)) != NULL)
  1940. {
  1941. if (::GetTopWindow(hWndChild) != NULL)
  1942. {
  1943. // children with the same ID as their parent have priority
  1944. pWndChild = GetDescendantWindow(hWndChild, nID, bOnlyPerm);
  1945. if (pWndChild != NULL)
  1946. return pWndChild;
  1947. }
  1948. // return temporary handle if allowed
  1949. if (!bOnlyPerm)
  1950. return CWnd::FromHandle(hWndChild);
  1951. // return only permanent handle
  1952. pWndChild = CWnd::FromHandlePermanent(hWndChild);
  1953. if (pWndChild != NULL)
  1954. return pWndChild;
  1955. }
  1956. // walk each child
  1957. for (hWndChild = ::GetTopWindow(hWnd); hWndChild != NULL;
  1958. hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  1959. {
  1960. pWndChild = GetDescendantWindow(hWndChild, nID, bOnlyPerm);
  1961. if (pWndChild != NULL)
  1962. return pWndChild;
  1963. }
  1964. return NULL; // not found
  1965. }
  1966. void PASCAL CWnd::SendMessageToDescendants(HWND hWnd, UINT message,
  1967. WPARAM wParam, LPARAM lParam, BOOL bDeep, BOOL bOnlyPerm)
  1968. {
  1969. // walk through HWNDs to avoid creating temporary CWnd objects
  1970. // unless we need to call this function recursively
  1971. for (HWND hWndChild = ::GetTopWindow(hWnd); hWndChild != NULL;
  1972. hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  1973. {
  1974. // if bOnlyPerm is TRUE, don't send to non-permanent windows
  1975. if (bOnlyPerm)
  1976. {
  1977. CWnd* pWnd = CWnd::FromHandlePermanent(hWndChild);
  1978. if (pWnd != NULL)
  1979. {
  1980. // call window proc directly since it is a C++ window
  1981. AfxCallWndProc(pWnd, pWnd->m_hWnd, message, wParam, lParam);
  1982. }
  1983. }
  1984. else
  1985. {
  1986. // send message with Windows SendMessage API
  1987. ::SendMessage(hWndChild, message, wParam, lParam);
  1988. }
  1989. if (bDeep && ::GetTopWindow(hWndChild) != NULL)
  1990. {
  1991. // send to child windows after parent
  1992. SendMessageToDescendants(hWndChild, message, wParam, lParam,
  1993. bDeep, bOnlyPerm);
  1994. }
  1995. }
  1996. }
  1997. /////////////////////////////////////////////////////////////////////////////
  1998. // Scroll bar helpers
  1999. // hook for CWnd functions
  2000. // only works for derived class (eg: CView) that override 'GetScrollBarCtrl'
  2001. // if the window doesn't have a _visible_ windows scrollbar - then
  2002. // look for a sibling with the appropriate ID
  2003. CScrollBar* CWnd::GetScrollBarCtrl(int) const
  2004. {
  2005. return NULL; // no special scrollers supported
  2006. }
  2007. int CWnd::SetScrollPos(int nBar, int nPos, BOOL bRedraw)
  2008. {
  2009. CScrollBar* pScrollBar;
  2010. if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
  2011. return pScrollBar->SetScrollPos(nPos, bRedraw);
  2012. else
  2013. return ::SetScrollPos(m_hWnd, nBar, nPos, bRedraw);
  2014. }
  2015. int CWnd::GetScrollPos(int nBar) const
  2016. {
  2017. CScrollBar* pScrollBar;
  2018. if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
  2019. return pScrollBar->GetScrollPos();
  2020. else
  2021. return ::GetScrollPos(m_hWnd, nBar);
  2022. }
  2023. void CWnd::SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw)
  2024. {
  2025. CScrollBar* pScrollBar;
  2026. if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
  2027. pScrollBar->SetScrollRange(nMinPos, nMaxPos, bRedraw);
  2028. else
  2029. ::SetScrollRange(m_hWnd, nBar, nMinPos, nMaxPos, bRedraw);
  2030. }
  2031. void CWnd::GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const
  2032. {
  2033. CScrollBar* pScrollBar;
  2034. if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
  2035. pScrollBar->GetScrollRange(lpMinPos, lpMaxPos);
  2036. else
  2037. ::GetScrollRange(m_hWnd, nBar, lpMinPos, lpMaxPos);
  2038. }
  2039. // Turn on/off non-control scrollbars
  2040. // for WS_?SCROLL scrollbars - show/hide them
  2041. // for control scrollbar - enable/disable them
  2042. void CWnd::EnableScrollBarCtrl(int nBar, BOOL bEnable)
  2043. {
  2044. CScrollBar* pScrollBar;
  2045. if (nBar == SB_BOTH)
  2046. {
  2047. EnableScrollBarCtrl(SB_HORZ, bEnable);
  2048. EnableScrollBarCtrl(SB_VERT, bEnable);
  2049. }
  2050. else if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
  2051. {
  2052. // control scrollbar - enable or disable
  2053. pScrollBar->EnableWindow(bEnable);
  2054. }
  2055. else
  2056. {
  2057. // WS_?SCROLL scrollbar - show or hide
  2058. ShowScrollBar(nBar, bEnable);
  2059. }
  2060. }
  2061. BOOL CWnd::SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw)
  2062. {
  2063. ASSERT(lpScrollInfo != NULL);
  2064. if (afxData.nWinVer < 0x333)
  2065. return FALSE;
  2066. HWND hWnd = m_hWnd;
  2067. CScrollBar* pScrollBar;
  2068. if (nBar != SB_CTL && (pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
  2069. {
  2070. hWnd = pScrollBar->m_hWnd;
  2071. nBar = SB_CTL;
  2072. }
  2073. lpScrollInfo->cbSize = sizeof(*lpScrollInfo);
  2074. ::SetScrollInfo(hWnd, nBar, lpScrollInfo, bRedraw);
  2075. return TRUE;
  2076. }
  2077. BOOL CWnd::GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, UINT nMask)
  2078. {
  2079. ASSERT(lpScrollInfo != NULL);
  2080. if (afxData.nWinVer < 0x333)
  2081. return FALSE;
  2082. HWND hWnd = m_hWnd;
  2083. CScrollBar* pScrollBar;
  2084. if (nBar != SB_CTL && (pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
  2085. {
  2086. hWnd = pScrollBar->m_hWnd;
  2087. nBar = SB_CTL;
  2088. }
  2089. lpScrollInfo->cbSize = sizeof(*lpScrollInfo);
  2090. lpScrollInfo->fMask = nMask;
  2091. return ::GetScrollInfo(hWnd, nBar, lpScrollInfo);
  2092. }
  2093. int CWnd::GetScrollLimit(int nBar)
  2094. {
  2095. int nMin, nMax;
  2096. GetScrollRange(nBar, &nMin, &nMax);
  2097. SCROLLINFO info;
  2098. if (GetScrollInfo(nBar, &info, SIF_PAGE))
  2099. {
  2100. nMax -= __max(info.nPage-1,0);
  2101. }
  2102. return nMax;
  2103. }
  2104. void CWnd::ScrollWindow(int xAmount, int yAmount,
  2105. LPCRECT lpRect, LPCRECT lpClipRect)
  2106. {
  2107. ASSERT(::IsWindow(m_hWnd));
  2108. if (IsWindowVisible() || lpRect != NULL || lpClipRect != NULL)
  2109. {
  2110. // When visible, let Windows do the scrolling
  2111. ::ScrollWindow(m_hWnd, xAmount, yAmount, lpRect, lpClipRect);
  2112. }
  2113. else
  2114. {
  2115. // Windows does not perform any scrolling if the window is
  2116. // not visible. This leaves child windows unscrolled.
  2117. // To account for this oversight, the child windows are moved
  2118. // directly instead.
  2119. HWND hWndChild = ::GetWindow(m_hWnd, GW_CHILD);
  2120. if (hWndChild != NULL)
  2121. {
  2122. for (; hWndChild != NULL;
  2123. hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  2124. {
  2125. CRect rect;
  2126. ::GetWindowRect(hWndChild, &rect);
  2127. ScreenToClient(&rect);
  2128. ::SetWindowPos(hWndChild, NULL,
  2129. rect.left+xAmount, rect.top+yAmount, 0, 0,
  2130. SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOZORDER);
  2131. }
  2132. }
  2133. }
  2134. #ifndef _AFX_NO_OCC_SUPPORT
  2135. if ((m_pCtrlCont == NULL) || (lpRect != NULL))
  2136. return;
  2137. // the following code is for OLE control containers only
  2138. m_pCtrlCont->ScrollChildren(xAmount, yAmount);
  2139. #endif // !_AFX_NO_OCC_SUPPORT
  2140. }
  2141. /////////////////////////////////////////////////////////////////////////////
  2142. // minimal layout support
  2143. void CWnd::RepositionBars(UINT nIDFirst, UINT nIDLast, UINT nIDLeftOver,
  2144. UINT nFlags, LPRECT lpRectParam, LPCRECT lpRectClient, BOOL bStretch)
  2145. {
  2146. ASSERT(nFlags == 0 || nFlags == reposQuery || nFlags == reposExtra);
  2147. // walk kids in order, control bars get the resize notification
  2148. // which allow them to shrink the client area
  2149. // remaining size goes to the 'nIDLeftOver' pane
  2150. // NOTE: nIDFirst->nIDLast are usually 0->0xffff
  2151. AFX_SIZEPARENTPARAMS layout;
  2152. HWND hWndLeftOver = NULL;
  2153. layout.bStretch = bStretch;
  2154. layout.sizeTotal.cx = layout.sizeTotal.cy = 0;
  2155. if (lpRectClient != NULL)
  2156. layout.rect = *lpRectClient; // starting rect comes from parameter
  2157. else
  2158. GetClientRect(&layout.rect); // starting rect comes from client rect
  2159. if (nFlags != reposQuery)
  2160. layout.hDWP = ::BeginDeferWindowPos(8); // reasonable guess
  2161. else
  2162. layout.hDWP = NULL; // not actually doing layout
  2163. for (HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
  2164. hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  2165. {
  2166. UINT nIDC = _AfxGetDlgCtrlID(hWndChild);
  2167. CWnd* pWnd = CWnd::FromHandlePermanent(hWndChild);
  2168. if (nIDC == nIDLeftOver)
  2169. hWndLeftOver = hWndChild;
  2170. else if (nIDC >= nIDFirst && nIDC <= nIDLast && pWnd != NULL)
  2171. ::SendMessage(hWndChild, WM_SIZEPARENT, 0, (LPARAM)&layout);
  2172. }
  2173. // if just getting the available rectangle, return it now...
  2174. if (nFlags == reposQuery)
  2175. {
  2176. ASSERT(lpRectParam != NULL);
  2177. if (bStretch)
  2178. ::CopyRect(lpRectParam, &layout.rect);
  2179. else
  2180. {
  2181. lpRectParam->left = lpRectParam->top = 0;
  2182. lpRectParam->right = layout.sizeTotal.cx;
  2183. lpRectParam->bottom = layout.sizeTotal.cy;
  2184. }
  2185. return;
  2186. }
  2187. // the rest is the client size of the left-over pane
  2188. if (nIDLeftOver != 0 && hWndLeftOver != NULL)
  2189. {
  2190. CWnd* pLeftOver = CWnd::FromHandle(hWndLeftOver);
  2191. // allow extra space as specified by lpRectBorder
  2192. if (nFlags == reposExtra)
  2193. {
  2194. ASSERT(lpRectParam != NULL);
  2195. layout.rect.left += lpRectParam->left;
  2196. layout.rect.top += lpRectParam->top;
  2197. layout.rect.right -= lpRectParam->right;
  2198. layout.rect.bottom -= lpRectParam->bottom;
  2199. }
  2200. // reposition the window
  2201. pLeftOver->CalcWindowRect(&layout.rect);
  2202. AfxRepositionWindow(&layout, hWndLeftOver, &layout.rect);
  2203. }
  2204. // move and resize all the windows at once!
  2205. if (layout.hDWP == NULL || !::EndDeferWindowPos(layout.hDWP))
  2206. TRACE0("Warning: DeferWindowPos failed - low system resources.\n");
  2207. }
  2208. void AFXAPI AfxRepositionWindow(AFX_SIZEPARENTPARAMS* lpLayout,
  2209. HWND hWnd, LPCRECT lpRect)
  2210. {
  2211. ASSERT(hWnd != NULL);
  2212. ASSERT(lpRect != NULL);
  2213. HWND hWndParent = ::GetParent(hWnd);
  2214. ASSERT(hWndParent != NULL);
  2215. if (lpLayout != NULL && lpLayout->hDWP == NULL)
  2216. return;
  2217. // first check if the new rectangle is the same as the current
  2218. CRect rectOld;
  2219. ::GetWindowRect(hWnd, rectOld);
  2220. ::ScreenToClient(hWndParent, &rectOld.TopLeft());
  2221. ::ScreenToClient(hWndParent, &rectOld.BottomRight());
  2222. if (::EqualRect(rectOld, lpRect))
  2223. return; // nothing to do
  2224. // try to use DeferWindowPos for speed, otherwise use SetWindowPos
  2225. if (lpLayout != NULL)
  2226. {
  2227. lpLayout->hDWP = ::DeferWindowPos(lpLayout->hDWP, hWnd, NULL,
  2228. lpRect->left, lpRect->top, lpRect->right - lpRect->left,
  2229. lpRect->bottom - lpRect->top, SWP_NOACTIVATE|SWP_NOZORDER);
  2230. }
  2231. else
  2232. {
  2233. ::SetWindowPos(hWnd, NULL, lpRect->left, lpRect->top,
  2234. lpRect->right - lpRect->left, lpRect->bottom - lpRect->top,
  2235. SWP_NOACTIVATE|SWP_NOZORDER);
  2236. }
  2237. }
  2238. void CWnd::CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType)
  2239. {
  2240. DWORD dwExStyle = GetExStyle();
  2241. if (nAdjustType == 0)
  2242. dwExStyle &= ~WS_EX_CLIENTEDGE;
  2243. ::AdjustWindowRectEx(lpClientRect, GetStyle(), FALSE, dwExStyle);
  2244. }
  2245. /////////////////////////////////////////////////////////////////////////////
  2246. // Special keyboard/system command processing
  2247. BOOL CWnd::HandleFloatingSysCommand(UINT nID, LPARAM lParam)
  2248. {
  2249. CWnd* pParent = GetTopLevelParent();
  2250. switch (nID & 0xfff0)
  2251. {
  2252. case SC_PREVWINDOW:
  2253. case SC_NEXTWINDOW:
  2254. if (LOWORD(lParam) == VK_F6 && pParent != NULL)
  2255. {
  2256. pParent->SetFocus();
  2257. return TRUE;
  2258. }
  2259. break;
  2260. case SC_CLOSE:
  2261. case SC_KEYMENU:
  2262. // Check lParam. If it is 0L, then the user may have done
  2263. // an Alt+Tab, so just ignore it. This breaks the ability to
  2264. // just press the Alt-key and have the first menu selected,
  2265. // but this is minor compared to what happens in the Alt+Tab
  2266. // case.
  2267. if ((nID & 0xfff0) == SC_CLOSE || lParam != 0L)
  2268. {
  2269. if (pParent != NULL)
  2270. {
  2271. // Sending the above WM_SYSCOMMAND may destroy the app,
  2272. // so we have to be careful about restoring activation
  2273. // and focus after sending it.
  2274. HWND hWndSave = m_hWnd;
  2275. HWND hWndFocus = ::GetFocus();
  2276. pParent->SetActiveWindow();
  2277. pParent->SendMessage(WM_SYSCOMMAND, nID, lParam);
  2278. // be very careful here...
  2279. if (::IsWindow(hWndSave))
  2280. ::SetActiveWindow(hWndSave);
  2281. if (::IsWindow(hWndFocus))
  2282. ::SetFocus(hWndFocus);
  2283. }
  2284. }
  2285. return TRUE;
  2286. }
  2287. return FALSE;
  2288. }
  2289. BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg)
  2290. {
  2291. ASSERT(hWndStop == NULL || ::IsWindow(hWndStop));
  2292. ASSERT(pMsg != NULL);
  2293. // walk from the target window up to the hWndStop window checking
  2294. // if any window wants to translate this message
  2295. for (HWND hWnd = pMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
  2296. {
  2297. CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
  2298. if (pWnd != NULL)
  2299. {
  2300. // target window is a C++ window
  2301. if (pWnd->PreTranslateMessage(pMsg))
  2302. return TRUE; // trapped by target window (eg: accelerators)
  2303. }
  2304. // got to hWndStop window without interest
  2305. if (hWnd == hWndStop)
  2306. break;
  2307. }
  2308. return FALSE; // no special processing
  2309. }
  2310. BOOL CWnd::SendChildNotifyLastMsg(LRESULT* pResult)
  2311. {
  2312. _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  2313. return OnChildNotify(pThreadState->m_lastSentMsg.message,
  2314. pThreadState->m_lastSentMsg.wParam, pThreadState->m_lastSentMsg.lParam, pResult);
  2315. }
  2316. BOOL PASCAL CWnd::ReflectLastMsg(HWND hWndChild, LRESULT* pResult)
  2317. {
  2318. // get the map, and if no map, then this message does not need reflection
  2319. CHandleMap* pMap = afxMapHWND();
  2320. if (pMap == NULL)
  2321. return FALSE;
  2322. // check if in permanent map, if it is reflect it (could be OLE control)
  2323. CWnd* pWnd = (CWnd*)pMap->LookupPermanent(hWndChild);
  2324. ASSERT(pWnd == NULL || pWnd->m_hWnd == hWndChild);
  2325. if (pWnd == NULL)
  2326. {
  2327. #ifndef _AFX_NO_OCC_SUPPORT
  2328. // check if the window is an OLE control
  2329. CWnd* pWndParent = (CWnd*)pMap->LookupPermanent(::GetParent(hWndChild));
  2330. if (pWndParent != NULL && pWndParent->m_pCtrlCont != NULL)
  2331. {
  2332. // If a matching control site exists, it's an OLE control
  2333. COleControlSite* pSite = (COleControlSite*)pWndParent->
  2334. m_pCtrlCont->m_siteMap.GetValueAt(hWndChild);
  2335. if (pSite != NULL)
  2336. {
  2337. CWnd wndTemp(hWndChild);
  2338. wndTemp.m_pCtrlSite = pSite;
  2339. LRESULT lResult = wndTemp.SendChildNotifyLastMsg(pResult);
  2340. wndTemp.m_hWnd = NULL;
  2341. return lResult;
  2342. }
  2343. }
  2344. #endif //!_AFX_NO_OCC_SUPPORT
  2345. return FALSE;
  2346. }
  2347. // only OLE controls and permanent windows will get reflected msgs
  2348. ASSERT(pWnd != NULL);
  2349. return pWnd->SendChildNotifyLastMsg(pResult);
  2350. }
  2351. BOOL CWnd::OnChildNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
  2352. {
  2353. #ifndef _AFX_NO_OCC_SUPPORT
  2354. if (m_pCtrlSite != NULL)
  2355. {
  2356. // first forward raw OCM_ messages to OLE control sources
  2357. LRESULT lResult = SendMessage(OCM__BASE+uMsg, wParam, lParam);
  2358. if (uMsg >= WM_CTLCOLORMSGBOX && uMsg <= WM_CTLCOLORSTATIC &&
  2359. (HBRUSH)lResult == NULL)
  2360. {
  2361. // for WM_CTLCOLOR msgs, returning NULL implies continue routing
  2362. return FALSE;
  2363. }
  2364. if (pResult != NULL)
  2365. *pResult = lResult;
  2366. return TRUE;
  2367. }
  2368. #endif
  2369. return ReflectChildNotify(uMsg, wParam, lParam, pResult);
  2370. }
  2371. BOOL CWnd::ReflectChildNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
  2372. {
  2373. // Note: reflected messages are send directly to CWnd::OnWndMsg
  2374. // and CWnd::OnCmdMsg for speed and because these messages are not
  2375. // routed by normal OnCmdMsg routing (they are only dispatched)
  2376. switch (uMsg)
  2377. {
  2378. // normal messages (just wParam, lParam through OnWndMsg)
  2379. case WM_HSCROLL:
  2380. case WM_VSCROLL:
  2381. case WM_PARENTNOTIFY:
  2382. case WM_DRAWITEM:
  2383. case WM_MEASUREITEM:
  2384. case WM_DELETEITEM:
  2385. case WM_VKEYTOITEM:
  2386. case WM_CHARTOITEM:
  2387. case WM_COMPAREITEM:
  2388. // reflect the message through the message map as WM_REFLECT_BASE+uMsg
  2389. return CWnd::OnWndMsg(WM_REFLECT_BASE+uMsg, wParam, lParam, pResult);
  2390. // special case for WM_COMMAND
  2391. case WM_COMMAND:
  2392. {
  2393. // reflect the message through the message map as OCM_COMMAND
  2394. int nCode = HIWORD(wParam);
  2395. if (CWnd::OnCmdMsg(0, MAKELONG(nCode, WM_REFLECT_BASE+WM_COMMAND), NULL, NULL))
  2396. {
  2397. if (pResult != NULL)
  2398. *pResult = 1;
  2399. return TRUE;
  2400. }
  2401. }
  2402. break;
  2403. // special case for WM_NOTIFY
  2404. case WM_NOTIFY:
  2405. {
  2406. // reflect the message through the message map as OCM_NOTIFY
  2407. NMHDR* pNMHDR = (NMHDR*)lParam;
  2408. int nCode = pNMHDR->code;
  2409. AFX_NOTIFY notify;
  2410. notify.pResult = pResult;
  2411. notify.pNMHDR = pNMHDR;
  2412. return CWnd::OnCmdMsg(0, MAKELONG(nCode, WM_REFLECT_BASE+WM_NOTIFY), &notify, NULL);
  2413. }
  2414. // other special cases (WM_CTLCOLOR family)
  2415. default:
  2416. if (uMsg >= WM_CTLCOLORMSGBOX && uMsg <= WM_CTLCOLORSTATIC)
  2417. {
  2418. // fill in special struct for compatiblity with 16-bit WM_CTLCOLOR
  2419. AFX_CTLCOLOR ctl;
  2420. ctl.hDC = (HDC)wParam;
  2421. ctl.nCtlType = uMsg - WM_CTLCOLORMSGBOX;
  2422. ASSERT(ctl.nCtlType >= CTLCOLOR_MSGBOX);
  2423. ASSERT(ctl.nCtlType <= CTLCOLOR_STATIC);
  2424. // reflect the message through the message map as OCM_CTLCOLOR
  2425. BOOL bResult = CWnd::OnWndMsg(WM_REFLECT_BASE+WM_CTLCOLOR, 0, (LPARAM)&ctl, pResult);
  2426. if ((HBRUSH)*pResult == NULL)
  2427. bResult = FALSE;
  2428. return bResult;
  2429. }
  2430. break;
  2431. }
  2432. return FALSE; // let the parent handle it
  2433. }
  2434. void CWnd::OnParentNotify(UINT message, LPARAM lParam)
  2435. {
  2436. if ((LOWORD(message) == WM_CREATE || LOWORD(message) == WM_DESTROY))
  2437. {
  2438. if (ReflectLastMsg((HWND)lParam))
  2439. return; // eat it
  2440. }
  2441. // not handled - do default
  2442. Default();
  2443. }
  2444. LRESULT CWnd::OnActivateTopLevel(WPARAM wParam, LPARAM)
  2445. {
  2446. if (LOWORD(wParam) == WA_INACTIVE)
  2447. {
  2448. _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
  2449. if (!(pThreadState->m_lastInfo.uFlags & TTF_ALWAYSTIP))
  2450. CancelToolTips(TRUE);
  2451. }
  2452. return 0;
  2453. }
  2454. void CWnd::OnSysColorChange()
  2455. {
  2456. CWinApp* pApp = AfxGetApp();
  2457. if (pApp != NULL && pApp->m_pMainWnd == this)
  2458. {
  2459. // recolor global brushes used by control bars
  2460. afxData.UpdateSysColors();
  2461. }
  2462. #ifndef _AFX_NO_CTL3D_SUPPORT
  2463. if (!afxContextIsDLL)
  2464. {
  2465. if (AfxGetThread() != NULL && AfxGetThread()->m_pMainWnd == this)
  2466. {
  2467. _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
  2468. // allow CTL3D32.DLL to be notified of color change
  2469. if (pCtl3dState->m_pfnColorChange != NULL)
  2470. (*pCtl3dState->m_pfnColorChange)();
  2471. }
  2472. }
  2473. #endif
  2474. // forward this message to all other child windows
  2475. if (!(GetStyle() & WS_CHILD))
  2476. SendMessageToDescendants(WM_SYSCOLORCHANGE, 0, 0L, TRUE, TRUE);
  2477. Default();
  2478. }
  2479. BOOL _afxGotScrollLines;
  2480. void CWnd::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
  2481. {
  2482. UNUSED_ALWAYS(uFlags);
  2483. UNUSED_ALWAYS(lpszSection);
  2484. #ifndef _AFX_NO_CTL3D_SUPPORT
  2485. if (!afxContextIsDLL)
  2486. {
  2487. _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
  2488. // allow CTL3D32.DLL to update from WIN.INI settings
  2489. if (AfxGetThread() != NULL && AfxGetThread()->m_pMainWnd == this &&
  2490. pCtl3dState->m_pfnWinIniChange != NULL)
  2491. {
  2492. (*pCtl3dState->m_pfnWinIniChange)();
  2493. }
  2494. }
  2495. #endif
  2496. // force refresh of settings that we cache
  2497. _afxGotScrollLines = FALSE;
  2498. CWnd::OnDisplayChange(0, 0); // to update system metrics, etc.
  2499. }
  2500. void CWnd::OnWinIniChange(LPCTSTR lpszSection)
  2501. {
  2502. UNUSED_ALWAYS(lpszSection);
  2503. // this function is provided for backward compatibility only
  2504. // it is called only in Windows NT 3.51; in Windows 95 and
  2505. // Windows NT, OnSettingChange is called
  2506. #ifndef _AFX_NO_CTL3D_SUPPORT
  2507. if (!afxContextIsDLL)
  2508. {
  2509. _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
  2510. // allow CTL3D32.DLL to update from WIN.INI settings
  2511. if (AfxGetThread() != NULL && AfxGetThread()->m_pMainWnd == this &&
  2512. pCtl3dState->m_pfnWinIniChange != NULL)
  2513. {
  2514. (*pCtl3dState->m_pfnWinIniChange)();
  2515. }
  2516. }
  2517. #endif
  2518. CWnd::OnDisplayChange(0, 0); // to update system metrics, etc.
  2519. }
  2520. void CWnd::OnDevModeChange(LPTSTR lpDeviceName)
  2521. {
  2522. CWinApp* pApp = AfxGetApp();
  2523. if (pApp != NULL && pApp->m_pMainWnd == this)
  2524. pApp->DevModeChange(lpDeviceName);
  2525. // forward this message to all other child windows
  2526. if (!(GetStyle() & WS_CHILD))
  2527. {
  2528. const MSG* pMsg = GetCurrentMessage();
  2529. SendMessageToDescendants(pMsg->message, pMsg->wParam, pMsg->lParam,
  2530. TRUE, TRUE);
  2531. }
  2532. }
  2533. BOOL CWnd::OnHelpInfo(HELPINFO* /*pHelpInfo*/)
  2534. {
  2535. if (!(GetStyle() & WS_CHILD))
  2536. {
  2537. CWnd* pMainWnd = AfxGetMainWnd();
  2538. if (pMainWnd != NULL &&
  2539. GetKeyState(VK_SHIFT) >= 0 &&
  2540. GetKeyState(VK_CONTROL) >= 0 &&
  2541. GetKeyState(VK_MENU) >= 0)
  2542. {
  2543. pMainWnd->SendMessage(WM_COMMAND, ID_HELP);
  2544. return TRUE;
  2545. }
  2546. }
  2547. return Default();
  2548. }
  2549. LRESULT CWnd::OnDisplayChange(WPARAM, LPARAM)
  2550. {
  2551. // update metrics if this window is the main window
  2552. if (AfxGetMainWnd() == this)
  2553. {
  2554. // update any system metrics cache
  2555. afxData.UpdateSysMetrics();
  2556. }
  2557. // forward this message to all other child windows
  2558. if (!(GetStyle() & WS_CHILD))
  2559. {
  2560. const MSG* pMsg = GetCurrentMessage();
  2561. SendMessageToDescendants(pMsg->message, pMsg->wParam, pMsg->lParam,
  2562. TRUE, TRUE);
  2563. }
  2564. return Default();
  2565. }
  2566. LRESULT CWnd::OnDragList(WPARAM, LPARAM lParam)
  2567. {
  2568. LPDRAGLISTINFO lpInfo = (LPDRAGLISTINFO)lParam;
  2569. ASSERT(lpInfo != NULL);
  2570. LRESULT lResult;
  2571. if (ReflectLastMsg(lpInfo->hWnd, &lResult))
  2572. return (int)lResult; // eat it
  2573. // not handled - do default
  2574. return (int)Default();
  2575. }
  2576. void CWnd::OnHScroll(UINT, UINT, CScrollBar* pScrollBar)
  2577. {
  2578. if (pScrollBar != NULL && pScrollBar->SendChildNotifyLastMsg())
  2579. return; // eat it
  2580. Default();
  2581. }
  2582. void CWnd::OnVScroll(UINT, UINT, CScrollBar* pScrollBar)
  2583. {
  2584. if (pScrollBar != NULL && pScrollBar->SendChildNotifyLastMsg())
  2585. return; // eat it
  2586. Default();
  2587. }
  2588. void CWnd::OnEnterIdle(UINT /*nWhy*/, CWnd* /*pWho*/)
  2589. {
  2590. // WINBUG: In some OLE inplace active scenarios, OLE will post a
  2591. // message instead of sending it. This causes so many WM_ENTERIDLE
  2592. // messages to be sent that tasks running in the background stop
  2593. // running. By dispatching the pending WM_ENTERIDLE messages
  2594. // when the first one is received, we trick Windows into thinking
  2595. // that only one was really sent and dispatched.
  2596. {
  2597. MSG msg;
  2598. while (PeekMessage(&msg, NULL, WM_ENTERIDLE, WM_ENTERIDLE, PM_REMOVE))
  2599. DispatchMessage(&msg);
  2600. }
  2601. Default();
  2602. }
  2603. HBRUSH CWnd::OnCtlColor(CDC*, CWnd* pWnd, UINT)
  2604. {
  2605. ASSERT(pWnd != NULL && pWnd->m_hWnd != NULL);
  2606. LRESULT lResult;
  2607. if (pWnd->SendChildNotifyLastMsg(&lResult))
  2608. return (HBRUSH)lResult; // eat it
  2609. return (HBRUSH)Default();
  2610. }
  2611. #ifndef _AFX_NO_GRAYDLG_SUPPORT
  2612. // special helper for Gray OnCtlColor routines
  2613. HBRUSH CWnd::OnGrayCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
  2614. {
  2615. LRESULT lResult;
  2616. if (pWnd->SendChildNotifyLastMsg(&lResult))
  2617. return (HBRUSH)lResult; // eat it
  2618. _AFX_WIN_STATE* pWinState = _afxWinState;
  2619. if (!GrayCtlColor(pDC->m_hDC, pWnd->GetSafeHwnd(), nCtlColor,
  2620. pWinState->m_hDlgBkBrush, pWinState->m_crDlgTextClr))
  2621. return (HBRUSH)Default();
  2622. return pWinState->m_hDlgBkBrush;
  2623. }
  2624. #endif //!_AFX_NO_GRAYDLG_SUPPORT
  2625. // implementation of OnCtlColor for default gray backgrounds
  2626. // (works for any window containing controls)
  2627. // return value of FALSE means caller must call DefWindowProc's default
  2628. // TRUE means that 'hbrGray' will be used and the appropriate text
  2629. // ('clrText') and background colors are set.
  2630. BOOL PASCAL CWnd::GrayCtlColor(HDC hDC, HWND hWnd, UINT nCtlColor,
  2631. HBRUSH hbrGray, COLORREF clrText)
  2632. {
  2633. if (hDC == NULL)
  2634. {
  2635. // sometimes Win32 passes a NULL hDC in the WM_CTLCOLOR message.
  2636. TRACE0("Warning: hDC is NULL in CWnd::GrayCtlColor; WM_CTLCOLOR not processed.\n");
  2637. return FALSE;
  2638. }
  2639. if (hbrGray == NULL ||
  2640. nCtlColor == CTLCOLOR_EDIT || nCtlColor == CTLCOLOR_MSGBOX ||
  2641. nCtlColor == CTLCOLOR_SCROLLBAR)
  2642. {
  2643. return FALSE;
  2644. }
  2645. if (nCtlColor == CTLCOLOR_LISTBOX)
  2646. {
  2647. // only handle requests to draw the space between edit and drop button
  2648. // in a drop-down combo (not a drop-down list)
  2649. if (!_AfxIsComboBoxControl(hWnd, (UINT)CBS_DROPDOWN))
  2650. return FALSE;
  2651. }
  2652. // set background color and return handle to brush
  2653. LOGBRUSH logbrush;
  2654. VERIFY(::GetObject(hbrGray, sizeof(LOGBRUSH), (LPVOID)&logbrush));
  2655. ::SetBkColor(hDC, logbrush.lbColor);
  2656. if (clrText == (COLORREF)-1)
  2657. clrText = ::GetSysColor(COLOR_WINDOWTEXT); // normal text
  2658. ::SetTextColor(hDC, clrText);
  2659. return TRUE;
  2660. }
  2661. #ifndef _AFX_NO_CTL3D_SUPPORT
  2662. LRESULT CWnd::OnQuery3dControls(WPARAM, LPARAM)
  2663. {
  2664. // This is message handler is not in CWnd's message map.
  2665. // It is placed in various derived classes' message maps to enable
  2666. // 3D controls for specific window types only.
  2667. return 0xFFFF; // CTL3D_ALL
  2668. }
  2669. #endif
  2670. /////////////////////////////////////////////////////////////////////////////
  2671. // 'dialog data' support
  2672. BOOL CWnd::UpdateData(BOOL bSaveAndValidate)
  2673. {
  2674. ASSERT(::IsWindow(m_hWnd)); // calling UpdateData before DoModal?
  2675. CDataExchange dx(this, bSaveAndValidate);
  2676. // prevent control notifications from being dispatched during UpdateData
  2677. _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
  2678. HWND hWndOldLockout = pThreadState->m_hLockoutNotifyWindow;
  2679. ASSERT(hWndOldLockout != m_hWnd); // must not recurse
  2680. pThreadState->m_hLockoutNotifyWindow = m_hWnd;
  2681. BOOL bOK = FALSE; // assume failure
  2682. TRY
  2683. {
  2684. DoDataExchange(&dx);
  2685. bOK = TRUE; // it worked
  2686. }
  2687. CATCH(CUserException, e)
  2688. {
  2689. // validation failed - user already alerted, fall through
  2690. ASSERT(!bOK);
  2691. // Note: DELETE_EXCEPTION_(e) not required
  2692. }
  2693. AND_CATCH_ALL(e)
  2694. {
  2695. // validation failed due to OOM or other resource failure
  2696. e->ReportError(MB_ICONEXCLAMATION, AFX_IDP_INTERNAL_FAILURE);
  2697. ASSERT(!bOK);
  2698. DELETE_EXCEPTION(e);
  2699. }
  2700. END_CATCH_ALL
  2701. pThreadState->m_hLockoutNotifyWindow = hWndOldLockout;
  2702. return bOK;
  2703. }
  2704. CDataExchange::CDataExchange(CWnd* pDlgWnd, BOOL bSaveAndValidate)
  2705. {
  2706. ASSERT_VALID(pDlgWnd);
  2707. m_bSaveAndValidate = bSaveAndValidate;
  2708. m_pDlgWnd = pDlgWnd;
  2709. m_hWndLastControl = NULL;
  2710. }
  2711. /////////////////////////////////////////////////////////////////////////////
  2712. // Centering dialog support (works for any non-child window)
  2713. void CWnd::CenterWindow(CWnd* pAlternateOwner)
  2714. {
  2715. ASSERT(::IsWindow(m_hWnd));
  2716. // determine owner window to center against
  2717. DWORD dwStyle = GetStyle();
  2718. HWND hWndCenter = pAlternateOwner->GetSafeHwnd();
  2719. if (pAlternateOwner == NULL)
  2720. {
  2721. if (dwStyle & WS_CHILD)
  2722. hWndCenter = ::GetParent(m_hWnd);
  2723. else
  2724. hWndCenter = ::GetWindow(m_hWnd, GW_OWNER);
  2725. if (hWndCenter != NULL)
  2726. {
  2727. // let parent determine alternate center window
  2728. HWND hWndTemp =
  2729. (HWND)::SendMessage(hWndCenter, WM_QUERYCENTERWND, 0, 0);
  2730. if (hWndTemp != NULL)
  2731. hWndCenter = hWndTemp;
  2732. }
  2733. }
  2734. // get coordinates of the window relative to its parent
  2735. CRect rcDlg;
  2736. GetWindowRect(&rcDlg);
  2737. CRect rcArea;
  2738. CRect rcCenter;
  2739. HWND hWndParent;
  2740. if (!(dwStyle & WS_CHILD))
  2741. {
  2742. // don't center against invisible or minimized windows
  2743. if (hWndCenter != NULL)
  2744. {
  2745. DWORD dwStyle = ::GetWindowLong(hWndCenter, GWL_STYLE);
  2746. if (!(dwStyle & WS_VISIBLE) || (dwStyle & WS_MINIMIZE))
  2747. hWndCenter = NULL;
  2748. }
  2749. MONITORINFO mi;
  2750. mi.cbSize = sizeof(mi);
  2751. // center within appropriate monitor coordinates
  2752. if (hWndCenter == NULL)
  2753. {
  2754. HWND hwDefault = AfxGetMainWnd()->GetSafeHwnd();
  2755. GetMonitorInfo(
  2756. MonitorFromWindow(hwDefault, MONITOR_DEFAULTTOPRIMARY), &mi);
  2757. rcCenter = mi.rcWork;
  2758. rcArea = mi.rcWork;
  2759. }
  2760. else
  2761. {
  2762. ::GetWindowRect(hWndCenter, &rcCenter);
  2763. GetMonitorInfo(
  2764. MonitorFromWindow(hWndCenter, MONITOR_DEFAULTTONEAREST), &mi);
  2765. rcArea = mi.rcWork;
  2766. }
  2767. }
  2768. else
  2769. {
  2770. // center within parent client coordinates
  2771. hWndParent = ::GetParent(m_hWnd);
  2772. ASSERT(::IsWindow(hWndParent));
  2773. ::GetClientRect(hWndParent, &rcArea);
  2774. ASSERT(::IsWindow(hWndCenter));
  2775. ::GetClientRect(hWndCenter, &rcCenter);
  2776. ::MapWindowPoints(hWndCenter, hWndParent, (POINT*)&rcCenter, 2);
  2777. }
  2778. // find dialog's upper left based on rcCenter
  2779. int xLeft = (rcCenter.left + rcCenter.right) / 2 - rcDlg.Width() / 2;
  2780. int yTop = (rcCenter.top + rcCenter.bottom) / 2 - rcDlg.Height() / 2;
  2781. // if the dialog is outside the screen, move it inside
  2782. if (xLeft < rcArea.left)
  2783. xLeft = rcArea.left;
  2784. else if (xLeft + rcDlg.Width() > rcArea.right)
  2785. xLeft = rcArea.right - rcDlg.Width();
  2786. if (yTop < rcArea.top)
  2787. yTop = rcArea.top;
  2788. else if (yTop + rcDlg.Height() > rcArea.bottom)
  2789. yTop = rcArea.bottom - rcDlg.Height();
  2790. // map screen coordinates to child coordinates
  2791. SetWindowPos(NULL, xLeft, yTop, -1, -1,
  2792. SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  2793. }
  2794. BOOL CWnd::CheckAutoCenter()
  2795. {
  2796. return TRUE;
  2797. }
  2798. /////////////////////////////////////////////////////////////////////////////
  2799. // Dialog initialization support
  2800. BOOL CWnd::ExecuteDlgInit(LPCTSTR lpszResourceName)
  2801. {
  2802. // find resource handle
  2803. LPVOID lpResource = NULL;
  2804. HGLOBAL hResource = NULL;
  2805. if (lpszResourceName != NULL)
  2806. {
  2807. HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_DLGINIT);
  2808. HRSRC hDlgInit = ::FindResource(hInst, lpszResourceName, RT_DLGINIT);
  2809. if (hDlgInit != NULL)
  2810. {
  2811. // load it
  2812. hResource = LoadResource(hInst, hDlgInit);
  2813. if (hResource == NULL)
  2814. return FALSE;
  2815. // lock it
  2816. lpResource = LockResource(hResource);
  2817. ASSERT(lpResource != NULL);
  2818. }
  2819. }
  2820. // execute it
  2821. BOOL bResult = ExecuteDlgInit(lpResource);
  2822. // cleanup
  2823. if (lpResource != NULL && hResource != NULL)
  2824. {
  2825. UnlockResource(hResource);
  2826. FreeResource(hResource);
  2827. }
  2828. return bResult;
  2829. }
  2830. BOOL CWnd::ExecuteDlgInit(LPVOID lpResource)
  2831. {
  2832. BOOL bSuccess = TRUE;
  2833. if (lpResource != NULL)
  2834. {
  2835. UNALIGNED WORD* lpnRes = (WORD*)lpResource;
  2836. while (bSuccess && *lpnRes != 0)
  2837. {
  2838. WORD nIDC = *lpnRes++;
  2839. WORD nMsg = *lpnRes++;
  2840. DWORD dwLen = *((UNALIGNED DWORD*&)lpnRes)++;
  2841. // In Win32 the WM_ messages have changed. They have
  2842. // to be translated from the 32-bit values to 16-bit
  2843. // values here.
  2844. #define WIN16_LB_ADDSTRING 0x0401
  2845. #define WIN16_CB_ADDSTRING 0x0403
  2846. #define AFX_CB_ADDSTRING 0x1234
  2847. // unfortunately, WIN16_CB_ADDSTRING == CBEM_INSERTITEM
  2848. if (nMsg == AFX_CB_ADDSTRING)
  2849. nMsg = CBEM_INSERTITEM;
  2850. else if (nMsg == WIN16_LB_ADDSTRING)
  2851. nMsg = LB_ADDSTRING;
  2852. else if (nMsg == WIN16_CB_ADDSTRING)
  2853. nMsg = CB_ADDSTRING;
  2854. // check for invalid/unknown message types
  2855. #ifdef _AFX_NO_OCC_SUPPORT
  2856. ASSERT(nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING ||
  2857. nMsg == CBEM_INSERTITEM);
  2858. #else
  2859. ASSERT(nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING ||
  2860. nMsg == CBEM_INSERTITEM ||
  2861. nMsg == WM_OCC_LOADFROMSTREAM ||
  2862. nMsg == WM_OCC_LOADFROMSTREAM_EX ||
  2863. nMsg == WM_OCC_LOADFROMSTORAGE ||
  2864. nMsg == WM_OCC_LOADFROMSTORAGE_EX ||
  2865. nMsg == WM_OCC_INITNEW);
  2866. #endif
  2867. #ifdef _DEBUG
  2868. // For AddStrings, the count must exactly delimit the
  2869. // string, including the NULL termination. This check
  2870. // will not catch all mal-formed ADDSTRINGs, but will
  2871. // catch some.
  2872. if (nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING || nMsg == CBEM_INSERTITEM)
  2873. ASSERT(*((LPBYTE)lpnRes + (UINT)dwLen - 1) == 0);
  2874. #endif
  2875. if (nMsg == CBEM_INSERTITEM)
  2876. {
  2877. USES_CONVERSION;
  2878. COMBOBOXEXITEM item;
  2879. item.mask = CBEIF_TEXT;
  2880. item.iItem = -1;
  2881. item.pszText = A2T(LPSTR(lpnRes));
  2882. if (::SendDlgItemMessage(m_hWnd, nIDC, nMsg, 0, (LPARAM) &item) == -1)
  2883. bSuccess = FALSE;
  2884. }
  2885. #ifndef _AFX_NO_OCC_SUPPORT
  2886. else if (nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING)
  2887. #endif // !_AFX_NO_OCC_SUPPORT
  2888. {
  2889. // List/Combobox returns -1 for error
  2890. if (::SendDlgItemMessageA(m_hWnd, nIDC, nMsg, 0, (LPARAM) lpnRes) == -1)
  2891. bSuccess = FALSE;
  2892. }
  2893. // skip past data
  2894. lpnRes = (WORD*)((LPBYTE)lpnRes + (UINT)dwLen);
  2895. }
  2896. }
  2897. // send update message to all controls after all other siblings loaded
  2898. if (bSuccess)
  2899. SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, FALSE, FALSE);
  2900. return bSuccess;
  2901. }
  2902. void CWnd::UpdateDialogControls(CCmdTarget* pTarget, BOOL bDisableIfNoHndler)
  2903. {
  2904. CCmdUI state;
  2905. CWnd wndTemp; // very temporary window just for CmdUI update
  2906. // walk all the kids - assume the IDs are for buttons
  2907. for (HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
  2908. hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  2909. {
  2910. // send to buttons
  2911. wndTemp.m_hWnd = hWndChild; // quick and dirty attach
  2912. state.m_nID = _AfxGetDlgCtrlID(hWndChild);
  2913. state.m_pOther = &wndTemp;
  2914. // check for reflect handlers in the child window
  2915. CWnd* pWnd = CWnd::FromHandlePermanent(hWndChild);
  2916. if (pWnd != NULL)
  2917. {
  2918. // call it directly to disable any routing
  2919. if (pWnd->CWnd::OnCmdMsg(0, MAKELONG(-1,
  2920. WM_COMMAND+WM_REFLECT_BASE), &state, NULL))
  2921. continue;
  2922. }
  2923. // check for handlers in the parent window
  2924. if (CWnd::OnCmdMsg(state.m_nID, CN_UPDATE_COMMAND_UI, &state, NULL))
  2925. continue;
  2926. // determine whether to disable when no handler exists
  2927. BOOL bDisableTemp = bDisableIfNoHndler;
  2928. if (bDisableTemp)
  2929. {
  2930. if ((wndTemp.SendMessage(WM_GETDLGCODE) & DLGC_BUTTON) == 0)
  2931. {
  2932. // non-button controls don't get automagically disabled
  2933. bDisableTemp = FALSE;
  2934. }
  2935. else
  2936. {
  2937. // only certain button controls get automagically disabled
  2938. UINT nStyle = (UINT)(wndTemp.GetStyle() & 0x0F);
  2939. if (nStyle == (UINT)BS_AUTOCHECKBOX ||
  2940. nStyle == (UINT)BS_AUTO3STATE ||
  2941. nStyle == (UINT)BS_GROUPBOX ||
  2942. nStyle == (UINT)BS_AUTORADIOBUTTON)
  2943. {
  2944. bDisableTemp = FALSE;
  2945. }
  2946. }
  2947. }
  2948. // check for handlers in the target (owner)
  2949. state.DoUpdate(pTarget, bDisableTemp);
  2950. }
  2951. wndTemp.m_hWnd = NULL; // quick and dirty detach
  2952. }
  2953. BOOL CWnd::PreTranslateInput(LPMSG lpMsg)
  2954. {
  2955. ASSERT(::IsWindow(m_hWnd));
  2956. // don't translate non-input events
  2957. if ((lpMsg->message < WM_KEYFIRST || lpMsg->message > WM_KEYLAST) &&
  2958. (lpMsg->message < WM_MOUSEFIRST || lpMsg->message > WM_MOUSELAST))
  2959. return FALSE;
  2960. return IsDialogMessage(lpMsg);
  2961. }
  2962. int CWnd::RunModalLoop(DWORD dwFlags)
  2963. {
  2964. ASSERT(::IsWindow(m_hWnd)); // window must be created
  2965. ASSERT(!(m_nFlags & WF_MODALLOOP)); // window must not already be in modal state
  2966. // for tracking the idle time state
  2967. BOOL bIdle = TRUE;
  2968. LONG lIdleCount = 0;
  2969. BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) && !(GetStyle() & WS_VISIBLE);
  2970. HWND hWndParent = ::GetParent(m_hWnd);
  2971. m_nFlags |= (WF_MODALLOOP|WF_CONTINUEMODAL);
  2972. MSG* pMsg = &AfxGetThread()->m_msgCur;
  2973. // acquire and dispatch messages until the modal state is done
  2974. for (;;)
  2975. {
  2976. ASSERT(ContinueModal());
  2977. // phase1: check to see if we can do idle work
  2978. while (bIdle &&
  2979. !::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE))
  2980. {
  2981. ASSERT(ContinueModal());
  2982. // show the dialog when the message queue goes idle
  2983. if (bShowIdle)
  2984. {
  2985. ShowWindow(SW_SHOWNORMAL);
  2986. UpdateWindow();
  2987. bShowIdle = FALSE;
  2988. }
  2989. // call OnIdle while in bIdle state
  2990. if (!(dwFlags & MLF_NOIDLEMSG) && hWndParent != NULL && lIdleCount == 0)
  2991. {
  2992. // send WM_ENTERIDLE to the parent
  2993. ::SendMessage(hWndParent, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd);
  2994. }
  2995. if ((dwFlags & MLF_NOKICKIDLE) ||
  2996. !SendMessage(WM_KICKIDLE, MSGF_DIALOGBOX, lIdleCount++))
  2997. {
  2998. // stop idle processing next time
  2999. bIdle = FALSE;
  3000. }
  3001. }
  3002. // phase2: pump messages while available
  3003. do
  3004. {
  3005. ASSERT(ContinueModal());
  3006. // pump message, but quit on WM_QUIT
  3007. if (!AfxGetThread()->PumpMessage())
  3008. {
  3009. AfxPostQuitMessage(0);
  3010. return -1;
  3011. }
  3012. // show the window when certain special messages rec'd
  3013. if (bShowIdle &&
  3014. (pMsg->message == 0x118 || pMsg->message == WM_SYSKEYDOWN))
  3015. {
  3016. ShowWindow(SW_SHOWNORMAL);
  3017. UpdateWindow();
  3018. bShowIdle = FALSE;
  3019. }
  3020. if (!ContinueModal())
  3021. goto ExitModal;
  3022. // reset "no idle" state after pumping "normal" message
  3023. if (AfxGetThread()->IsIdleMessage(pMsg))
  3024. {
  3025. bIdle = TRUE;
  3026. lIdleCount = 0;
  3027. }
  3028. } while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE));
  3029. }
  3030. ExitModal:
  3031. m_nFlags &= ~(WF_MODALLOOP|WF_CONTINUEMODAL);
  3032. return m_nModalResult;
  3033. }
  3034. BOOL CWnd::ContinueModal()
  3035. {
  3036. return m_nFlags & WF_CONTINUEMODAL;
  3037. }
  3038. void CWnd::EndModalLoop(int nResult)
  3039. {
  3040. ASSERT(::IsWindow(m_hWnd));
  3041. // this result will be returned from CWnd::RunModalLoop
  3042. m_nModalResult = nResult;
  3043. // make sure a message goes through to exit the modal loop
  3044. if (m_nFlags & WF_CONTINUEMODAL)
  3045. {
  3046. m_nFlags &= ~WF_CONTINUEMODAL;
  3047. PostMessage(WM_NULL);
  3048. }
  3049. }
  3050. #ifndef _AFX_NO_OCC_SUPPORT
  3051. BOOL CWnd::SetOccDialogInfo(_AFX_OCC_DIALOG_INFO*)
  3052. {
  3053. ASSERT(FALSE); // this class doesn't support dialog creation
  3054. return FALSE;
  3055. }
  3056. #endif
  3057. /////////////////////////////////////////////////////////////////////////////
  3058. // Standard init called by WinMain
  3059. AFX_STATIC BOOL AFXAPI _AfxRegisterWithIcon(WNDCLASS* pWndCls,
  3060. LPCTSTR lpszClassName, UINT nIDIcon)
  3061. {
  3062. pWndCls->lpszClassName = lpszClassName;
  3063. HINSTANCE hInst = AfxFindResourceHandle(
  3064. MAKEINTRESOURCE(nIDIcon), RT_GROUP_ICON);
  3065. if ((pWndCls->hIcon = ::LoadIcon(hInst, MAKEINTRESOURCE(nIDIcon))) == NULL)
  3066. {
  3067. // use default icon
  3068. pWndCls->hIcon = ::LoadIcon(NULL, IDI_APPLICATION);
  3069. }
  3070. return AfxRegisterClass(pWndCls);
  3071. }
  3072. LONG AFXAPI _AfxInitCommonControls(LPINITCOMMONCONTROLSEX lpInitCtrls, LONG fToRegister)
  3073. {
  3074. ASSERT(fToRegister != 0);
  3075. #ifndef _AFXDLL
  3076. HINSTANCE hInstBefore = ::GetModuleHandleA("COMCTL32.DLL");
  3077. #endif
  3078. // load the COMCTL32.DLL library because it may not be loaded yet (delayload)
  3079. HINSTANCE hInst = ::LoadLibraryA("COMCTL32.DLL");
  3080. if (hInst == NULL)
  3081. return 0;
  3082. LONG lResult = 0;
  3083. // attempt to get/call InitCommonControlsEx
  3084. BOOL (STDAPICALLTYPE* pfnInit)(LPINITCOMMONCONTROLSEX lpInitCtrls) = NULL;
  3085. (FARPROC&)pfnInit = ::GetProcAddress(hInst, "InitCommonControlsEx");
  3086. if (pfnInit == NULL)
  3087. {
  3088. // not there, so call InitCommonControls if possible
  3089. if ((fToRegister & AFX_WIN95CTLS_MASK) == fToRegister)
  3090. {
  3091. InitCommonControls();
  3092. lResult = AFX_WIN95CTLS_MASK;
  3093. }
  3094. }
  3095. #ifdef _AFXDLL
  3096. else if (InitCommonControlsEx(lpInitCtrls))
  3097. #else
  3098. else if ((*pfnInit)(lpInitCtrls))
  3099. #endif
  3100. {
  3101. // InitCommonControlsEx was successful so return the full mask
  3102. lResult = fToRegister;
  3103. #ifndef _AFXDLL
  3104. if (hInstBefore == NULL)
  3105. {
  3106. // In the case that we are statically linked and COMCTL32.DLL
  3107. // was not loaded before we loaded it with LoadLibrary in this
  3108. // function, that indicates that the calling module is linked
  3109. // with /delayload:comctl32.dll, and in this case we have to do
  3110. // something to cause COMCTL32.DLL to stay loaded. The only thing
  3111. // we can do is to call a COMCTL32.DLL API which will cause the
  3112. // CRT's delay load helpers to get called and will cause the DLL
  3113. // to get loaded. We choose to call InitCommonControls because
  3114. // it exists in the original COMCTL32.DLL and it doesn't really
  3115. // do any harm to call it, except for the time it takes to
  3116. // register the set of original Windows 95 classes.
  3117. // If this isn't done our FreeLibrary call below will cause
  3118. // COMCTL32.DLL to go away, undoing the registration.
  3119. InitCommonControls();
  3120. lResult |= AFX_WIN95CTLS_MASK;
  3121. }
  3122. #endif
  3123. }
  3124. // free the library reference and return the result
  3125. FreeLibrary(hInst);
  3126. return lResult;
  3127. }
  3128. BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)
  3129. {
  3130. // mask off all classes that are already registered
  3131. AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  3132. fToRegister &= ~pModuleState->m_fRegisteredClasses;
  3133. if (fToRegister == 0)
  3134. return TRUE;
  3135. LONG fRegisteredClasses = 0;
  3136. // common initialization
  3137. WNDCLASS wndcls;
  3138. memset(&wndcls, 0, sizeof(WNDCLASS)); // start with NULL defaults
  3139. wndcls.lpfnWndProc = DefWindowProc;
  3140. wndcls.hInstance = AfxGetInstanceHandle();
  3141. wndcls.hCursor = afxData.hcurArrow;
  3142. INITCOMMONCONTROLSEX init;
  3143. init.dwSize = sizeof(init);
  3144. // work to register classes as specified by fToRegister, populate fRegisteredClasses as we go
  3145. if (fToRegister & AFX_WND_REG)
  3146. {
  3147. // Child windows - no brush, no icon, safest default class styles
  3148. wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  3149. wndcls.lpszClassName = _afxWnd;
  3150. if (AfxRegisterClass(&wndcls))
  3151. fRegisteredClasses |= AFX_WND_REG;
  3152. }
  3153. if (fToRegister & AFX_WNDOLECONTROL_REG)
  3154. {
  3155. // OLE Control windows - use parent DC for speed
  3156. wndcls.style |= CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  3157. wndcls.lpszClassName = _afxWndOleControl;
  3158. if (AfxRegisterClass(&wndcls))
  3159. fRegisteredClasses |= AFX_WNDOLECONTROL_REG;
  3160. }
  3161. if (fToRegister & AFX_WNDCONTROLBAR_REG)
  3162. {
  3163. // Control bar windows
  3164. wndcls.style = 0; // control bars don't handle double click
  3165. wndcls.lpszClassName = _afxWndControlBar;
  3166. wndcls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
  3167. if (AfxRegisterClass(&wndcls))
  3168. fRegisteredClasses |= AFX_WNDCONTROLBAR_REG;
  3169. }
  3170. if (fToRegister & AFX_WNDMDIFRAME_REG)
  3171. {
  3172. // MDI Frame window (also used for splitter window)
  3173. wndcls.style = CS_DBLCLKS;
  3174. wndcls.hbrBackground = NULL;
  3175. if (_AfxRegisterWithIcon(&wndcls, _afxWndMDIFrame, AFX_IDI_STD_MDIFRAME))
  3176. fRegisteredClasses |= AFX_WNDMDIFRAME_REG;
  3177. }
  3178. if (fToRegister & AFX_WNDFRAMEORVIEW_REG)
  3179. {
  3180. // SDI Frame or MDI Child windows or views - normal colors
  3181. wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  3182. wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  3183. if (_AfxRegisterWithIcon(&wndcls, _afxWndFrameOrView, AFX_IDI_STD_FRAME))
  3184. fRegisteredClasses |= AFX_WNDFRAMEORVIEW_REG;
  3185. }
  3186. if (fToRegister & AFX_WNDCOMMCTLS_REG)
  3187. {
  3188. // this flag is compatible with the old InitCommonControls() API
  3189. init.dwICC = ICC_WIN95_CLASSES;
  3190. fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WIN95CTLS_MASK);
  3191. fToRegister &= ~AFX_WIN95CTLS_MASK;
  3192. }
  3193. if (fToRegister & AFX_WNDCOMMCTL_UPDOWN_REG)
  3194. {
  3195. init.dwICC = ICC_UPDOWN_CLASS;
  3196. fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_UPDOWN_REG);
  3197. }
  3198. if (fToRegister & AFX_WNDCOMMCTL_TREEVIEW_REG)
  3199. {
  3200. init.dwICC = ICC_TREEVIEW_CLASSES;
  3201. fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_TREEVIEW_REG);
  3202. }
  3203. if (fToRegister & AFX_WNDCOMMCTL_TAB_REG)
  3204. {
  3205. init.dwICC = ICC_TAB_CLASSES;
  3206. fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_TAB_REG);
  3207. }
  3208. if (fToRegister & AFX_WNDCOMMCTL_PROGRESS_REG)
  3209. {
  3210. init.dwICC = ICC_PROGRESS_CLASS;
  3211. fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_PROGRESS_REG);
  3212. }
  3213. if (fToRegister & AFX_WNDCOMMCTL_LISTVIEW_REG)
  3214. {
  3215. init.dwICC = ICC_LISTVIEW_CLASSES;
  3216. fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_LISTVIEW_REG);
  3217. }
  3218. if (fToRegister & AFX_WNDCOMMCTL_HOTKEY_REG)
  3219. {
  3220. init.dwICC = ICC_HOTKEY_CLASS;
  3221. fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_HOTKEY_REG);
  3222. }
  3223. if (fToRegister & AFX_WNDCOMMCTL_BAR_REG)
  3224. {
  3225. init.dwICC = ICC_BAR_CLASSES;
  3226. fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_BAR_REG);
  3227. }
  3228. if (fToRegister & AFX_WNDCOMMCTL_ANIMATE_REG)
  3229. {
  3230. init.dwICC = ICC_ANIMATE_CLASS;
  3231. fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_ANIMATE_REG);
  3232. }
  3233. if (fToRegister & AFX_WNDCOMMCTL_INTERNET_REG)
  3234. {
  3235. init.dwICC = ICC_INTERNET_CLASSES;
  3236. fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_INTERNET_REG);
  3237. }
  3238. if (fToRegister & AFX_WNDCOMMCTL_COOL_REG)
  3239. {
  3240. init.dwICC = ICC_COOL_CLASSES;
  3241. fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_COOL_REG);
  3242. }
  3243. if (fToRegister & AFX_WNDCOMMCTL_USEREX_REG)
  3244. {
  3245. init.dwICC = ICC_USEREX_CLASSES;
  3246. fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_USEREX_REG);
  3247. }
  3248. if (fToRegister & AFX_WNDCOMMCTL_DATE_REG)
  3249. {
  3250. init.dwICC = ICC_DATE_CLASSES;
  3251. fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_DATE_REG);
  3252. }
  3253. // save new state of registered controls
  3254. pModuleState->m_fRegisteredClasses |= fRegisteredClasses;
  3255. // special case for all common controls registered, turn on AFX_WNDCOMMCTLS_REG
  3256. if ((pModuleState->m_fRegisteredClasses & AFX_WIN95CTLS_MASK) == AFX_WIN95CTLS_MASK)
  3257. {
  3258. pModuleState->m_fRegisteredClasses |= AFX_WNDCOMMCTLS_REG;
  3259. fRegisteredClasses |= AFX_WNDCOMMCTLS_REG;
  3260. }
  3261. // must have registered at least as mamy classes as requested
  3262. return (fToRegister & fRegisteredClasses) == fToRegister;
  3263. }
  3264. /////////////////////////////////////////////////////////////////////////////
  3265. // CFrameWnd (here for library granularity)
  3266. BOOL CWnd::IsFrameWnd() const
  3267. {
  3268. return FALSE;
  3269. }
  3270. BOOL CFrameWnd::IsFrameWnd() const
  3271. {
  3272. return TRUE;
  3273. }
  3274. BOOL CFrameWnd::IsTracking() const
  3275. {
  3276. return m_nIDTracking != 0 &&
  3277. m_nIDTracking != AFX_IDS_HELPMODEMESSAGE &&
  3278. m_nIDTracking != AFX_IDS_IDLEMESSAGE;
  3279. }
  3280. /////////////////////////////////////////////////////////////////////////////
  3281. // CTL3D support
  3282. #ifndef _AFX_NO_CTL3D_SUPPORT
  3283. // Use SubclassCtl3d to add CTL3D support to an already subclassed control
  3284. // Usually only necessary if the control does not have one of the standard
  3285. // Windows class names.
  3286. BOOL CWnd::SubclassCtl3d(int nControlType)
  3287. {
  3288. ASSERT(!afxContextIsDLL); // Should only be called by apps
  3289. if (afxContextIsDLL)
  3290. return FALSE;
  3291. ASSERT(m_hWnd != NULL);
  3292. _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
  3293. if (nControlType == -1)
  3294. {
  3295. if (pCtl3dState->m_pfnSubclassCtl != NULL)
  3296. return (*pCtl3dState->m_pfnSubclassCtl)(m_hWnd);
  3297. }
  3298. else
  3299. {
  3300. if (pCtl3dState->m_pfnSubclassCtlEx != NULL)
  3301. return (*pCtl3dState->m_pfnSubclassCtlEx)(m_hWnd, nControlType);
  3302. }
  3303. return FALSE;
  3304. }
  3305. // Use SubclassDlg3d to add CTL3D support to an entire window.
  3306. // Any windows created on the window will be automatically subclassed.
  3307. BOOL CWnd::SubclassDlg3d(DWORD dwMask)
  3308. {
  3309. ASSERT(!afxContextIsDLL); // Should only be called by apps
  3310. if (afxContextIsDLL)
  3311. return FALSE;
  3312. ASSERT(m_hWnd != NULL);
  3313. _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
  3314. if (pCtl3dState->m_pfnSubclassDlgEx != NULL)
  3315. return pCtl3dState->m_pfnSubclassDlgEx(m_hWnd, dwMask);
  3316. return FALSE;
  3317. }
  3318. #endif //!_AFX_NO_CTL3D_SUPPORT
  3319. //this function can't be inlined because of _afxShell
  3320. void CWnd::DragAcceptFiles(BOOL bAccept)
  3321. {
  3322. ASSERT(::IsWindow(m_hWnd));
  3323. ::DragAcceptFiles(m_hWnd, bAccept);
  3324. }
  3325. /////////////////////////////////////////////////////////////////////////////
  3326. // Extra CWnd support for dynamic subclassing of controls
  3327. BOOL CWnd::SubclassWindow(HWND hWnd)
  3328. {
  3329. if (!Attach(hWnd))
  3330. return FALSE;
  3331. // allow any other subclassing to occur
  3332. PreSubclassWindow();
  3333. // now hook into the AFX WndProc
  3334. WNDPROC* lplpfn = GetSuperWndProcAddr();
  3335. WNDPROC oldWndProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC,
  3336. (DWORD)AfxGetAfxWndProc());
  3337. ASSERT(oldWndProc != (WNDPROC)AfxGetAfxWndProc());
  3338. if (*lplpfn == NULL)
  3339. *lplpfn = oldWndProc; // the first control of that type created
  3340. #ifdef _DEBUG
  3341. else if (*lplpfn != oldWndProc)
  3342. {
  3343. TRACE0("Error: Trying to use SubclassWindow with incorrect CWnd\n");
  3344. TRACE0("\tderived class.\n");
  3345. TRACE3("\thWnd = $%04X (nIDC=$%04X) is not a %hs.\n", (UINT)hWnd,
  3346. _AfxGetDlgCtrlID(hWnd), GetRuntimeClass()->m_lpszClassName);
  3347. ASSERT(FALSE);
  3348. // undo the subclassing if continuing after assert
  3349. ::SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)oldWndProc);
  3350. }
  3351. #endif
  3352. return TRUE;
  3353. }
  3354. BOOL CWnd::SubclassDlgItem(UINT nID, CWnd* pParent)
  3355. {
  3356. ASSERT(pParent != NULL);
  3357. ASSERT(::IsWindow(pParent->m_hWnd));
  3358. // check for normal dialog control first
  3359. HWND hWndControl = ::GetDlgItem(pParent->m_hWnd, nID);
  3360. if (hWndControl != NULL)
  3361. return SubclassWindow(hWndControl);
  3362. #ifndef _AFX_NO_OCC_SUPPORT
  3363. if (pParent->m_pCtrlCont != NULL)
  3364. {
  3365. // normal dialog control not found
  3366. COleControlSite* pSite = pParent->m_pCtrlCont->FindItem(nID);
  3367. if (pSite != NULL)
  3368. {
  3369. ASSERT(pSite->m_hWnd != NULL);
  3370. VERIFY(SubclassWindow(pSite->m_hWnd));
  3371. #ifndef _AFX_NO_OCC_SUPPORT
  3372. // If the control has reparented itself (e.g., invisible control),
  3373. // make sure that the CWnd gets properly wired to its control site.
  3374. if (pParent->m_hWnd != ::GetParent(pSite->m_hWnd))
  3375. AttachControlSite(pParent);
  3376. #endif //!_AFX_NO_OCC_SUPPORT
  3377. return TRUE;
  3378. }
  3379. }
  3380. #endif
  3381. return FALSE; // control not found
  3382. }
  3383. HWND CWnd::UnsubclassWindow()
  3384. {
  3385. ASSERT(::IsWindow(m_hWnd));
  3386. // set WNDPROC back to original value
  3387. WNDPROC* lplpfn = GetSuperWndProcAddr();
  3388. SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)*lplpfn);
  3389. *lplpfn = NULL;
  3390. // and Detach the HWND from the CWnd object
  3391. return Detach();
  3392. }
  3393. ////////////////////////////////////////////////////////////////////////////
  3394. // out-of-line inlines for binary compatibility
  3395. #ifdef _AFXDLL
  3396. #ifndef _DEBUG
  3397. CPoint::CPoint(POINT initPt)
  3398. { *(POINT*)this = initPt; }
  3399. #endif
  3400. #endif
  3401. #ifdef AFX_INIT_SEG
  3402. #pragma code_seg(AFX_INIT_SEG)
  3403. #endif
  3404. IMPLEMENT_DYNCREATE(CWnd, CCmdTarget)
  3405. IMPLEMENT_DYNCREATE(CTempWnd, CWnd);
  3406. #pragma warning(disable: 4074)
  3407. #pragma init_seg(compiler)
  3408. IMPLEMENT_FIXED_ALLOC(CTempWnd, 64);
  3409. /////////////////////////////////////////////////////////////////////////////