winfrm.cpp 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172
  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. #include <dde.h> // for DDE execute shell requests
  12. #ifdef AFX_CORE4_SEG
  13. #pragma code_seg(AFX_CORE4_SEG)
  14. #endif
  15. #ifdef _DEBUG
  16. #undef THIS_FILE
  17. static char THIS_FILE[] = __FILE__;
  18. #endif
  19. #define new DEBUG_NEW
  20. /////////////////////////////////////////////////////////////////////////////
  21. // CRect for creating windows with the default position/size
  22. const AFX_DATADEF CRect CFrameWnd::rectDefault(
  23. CW_USEDEFAULT, CW_USEDEFAULT,
  24. 0 /* 2*CW_USEDEFAULT */, 0 /* 2*CW_USEDEFAULT */);
  25. /////////////////////////////////////////////////////////////////////////////
  26. // CFrameWnd
  27. // register for Windows 95 or Windows NT 3.51
  28. AFX_STATIC UINT _afxMsgMouseWheel =
  29. (((::GetVersion() & 0x80000000) && LOBYTE(LOWORD(::GetVersion()) == 4)) ||
  30. (!(::GetVersion() & 0x80000000) && LOBYTE(LOWORD(::GetVersion()) == 3)))
  31. ? ::RegisterWindowMessage(MSH_MOUSEWHEEL) : 0;
  32. BEGIN_MESSAGE_MAP(CFrameWnd, CWnd)
  33. //{{AFX_MSG_MAP(CFrameWnd)
  34. ON_WM_INITMENU()
  35. ON_WM_INITMENUPOPUP()
  36. ON_WM_MENUSELECT()
  37. ON_MESSAGE(WM_POPMESSAGESTRING, OnPopMessageString)
  38. ON_MESSAGE(WM_SETMESSAGESTRING, OnSetMessageString)
  39. ON_MESSAGE(WM_HELPPROMPTADDR, OnHelpPromptAddr)
  40. ON_MESSAGE_VOID(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)
  41. ON_WM_ENTERIDLE()
  42. ON_WM_HSCROLL()
  43. ON_WM_VSCROLL()
  44. ON_WM_SETFOCUS()
  45. ON_WM_CREATE()
  46. ON_WM_DESTROY()
  47. ON_WM_CLOSE()
  48. ON_WM_SIZE()
  49. ON_WM_ERASEBKGND()
  50. ON_WM_ACTIVATE()
  51. ON_WM_NCACTIVATE()
  52. ON_WM_SYSCOMMAND()
  53. ON_WM_DROPFILES()
  54. ON_WM_QUERYENDSESSION()
  55. ON_WM_ENDSESSION()
  56. ON_WM_SETCURSOR()
  57. ON_WM_ENABLE()
  58. // OLE palette support
  59. ON_WM_QUERYNEWPALETTE()
  60. ON_WM_PALETTECHANGED()
  61. ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp)
  62. ON_MESSAGE(WM_HELPHITTEST, OnHelpHitTest)
  63. ON_MESSAGE(WM_ACTIVATETOPLEVEL, OnActivateTopLevel)
  64. // turning on and off standard frame gadgetry
  65. ON_UPDATE_COMMAND_UI(ID_VIEW_STATUS_BAR, OnUpdateControlBarMenu)
  66. ON_COMMAND_EX(ID_VIEW_STATUS_BAR, OnBarCheck)
  67. ON_UPDATE_COMMAND_UI(ID_VIEW_TOOLBAR, OnUpdateControlBarMenu)
  68. ON_COMMAND_EX(ID_VIEW_TOOLBAR, OnBarCheck)
  69. ON_UPDATE_COMMAND_UI(ID_VIEW_REBAR, OnUpdateControlBarMenu)
  70. ON_COMMAND_EX(ID_VIEW_REBAR, OnBarCheck)
  71. // turning on and off standard mode indicators
  72. ON_UPDATE_COMMAND_UI(ID_INDICATOR_CAPS, OnUpdateKeyIndicator)
  73. ON_UPDATE_COMMAND_UI(ID_INDICATOR_NUM, OnUpdateKeyIndicator)
  74. ON_UPDATE_COMMAND_UI(ID_INDICATOR_SCRL, OnUpdateKeyIndicator)
  75. ON_UPDATE_COMMAND_UI(ID_INDICATOR_KANA, OnUpdateKeyIndicator)
  76. // standard help handling
  77. ON_UPDATE_COMMAND_UI(ID_CONTEXT_HELP, OnUpdateContextHelp)
  78. // toolbar "tooltip" notification
  79. ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
  80. ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
  81. //}}AFX_MSG_MAP
  82. // message handling for standard DDE commands
  83. ON_MESSAGE(WM_DDE_INITIATE, OnDDEInitiate)
  84. ON_MESSAGE(WM_DDE_EXECUTE, OnDDEExecute)
  85. ON_MESSAGE(WM_DDE_TERMINATE, OnDDETerminate)
  86. ON_REGISTERED_MESSAGE(_afxMsgMouseWheel, OnRegisteredMouseWheel)
  87. END_MESSAGE_MAP()
  88. /////////////////////////////////////////////////////////////////////////////
  89. // CFrameWnd construction/destruction
  90. CFrameWnd::CFrameWnd()
  91. {
  92. ASSERT(m_hWnd == NULL);
  93. m_nWindow = -1; // unknown window ID
  94. m_bAutoMenuEnable = TRUE; // auto enable on by default
  95. m_lpfnCloseProc = NULL;
  96. m_hMenuDefault = NULL;
  97. m_hAccelTable = NULL;
  98. m_nIDHelp = 0;
  99. m_nIDTracking = 0;
  100. m_nIDLastMessage = 0;
  101. m_pViewActive = NULL;
  102. m_cModalStack = 0; // initialize modality support
  103. m_phWndDisable = NULL;
  104. m_pNotifyHook = NULL;
  105. m_hMenuAlt = NULL;
  106. m_nIdleFlags = 0; // no idle work at start
  107. m_rectBorder.SetRectEmpty();
  108. m_bHelpMode = HELP_INACTIVE; // not in Shift+F1 help mode
  109. m_dwPromptContext = 0;
  110. m_pNextFrameWnd = NULL; // not in list yet
  111. m_bInRecalcLayout = FALSE;
  112. m_pFloatingFrameClass = NULL;
  113. m_nShowDelay = -1; // no delay pending
  114. AddFrameWnd();
  115. }
  116. CFrameWnd::~CFrameWnd()
  117. {
  118. RemoveFrameWnd();
  119. if (m_phWndDisable != NULL)
  120. delete[] (void*)m_phWndDisable;
  121. }
  122. void CFrameWnd::AddFrameWnd()
  123. {
  124. // hook it into the CFrameWnd list
  125. AFX_MODULE_THREAD_STATE* pState = _AFX_CMDTARGET_GETSTATE()->m_thread;
  126. pState->m_frameList.AddHead(this);
  127. }
  128. void CFrameWnd::RemoveFrameWnd()
  129. {
  130. // remove this frame window from the list of frame windows
  131. AFX_MODULE_THREAD_STATE* pState = _AFX_CMDTARGET_GETSTATE()->m_thread;
  132. pState->m_frameList.Remove(this);
  133. }
  134. /////////////////////////////////////////////////////////////////////////////
  135. // Special processing etc
  136. BOOL CFrameWnd::LoadAccelTable(LPCTSTR lpszResourceName)
  137. {
  138. ASSERT(m_hAccelTable == NULL); // only do once
  139. ASSERT(lpszResourceName != NULL);
  140. HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_ACCELERATOR);
  141. m_hAccelTable = ::LoadAccelerators(hInst, lpszResourceName);
  142. return (m_hAccelTable != NULL);
  143. }
  144. HACCEL CFrameWnd::GetDefaultAccelerator()
  145. {
  146. // use document specific accelerator table over m_hAccelTable
  147. HACCEL hAccelTable = m_hAccelTable;
  148. HACCEL hAccel;
  149. CDocument* pDoc = GetActiveDocument();
  150. if (pDoc != NULL && (hAccel = pDoc->GetDefaultAccelerator()) != NULL)
  151. hAccelTable = hAccel;
  152. return hAccelTable;
  153. }
  154. BOOL CFrameWnd::PreTranslateMessage(MSG* pMsg)
  155. {
  156. // check for special cancel modes for combo boxes
  157. if (pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_NCLBUTTONDOWN)
  158. AfxCancelModes(pMsg->hwnd); // filter clicks
  159. // allow tooltip messages to be filtered
  160. if (CWnd::PreTranslateMessage(pMsg))
  161. return TRUE;
  162. #ifndef _AFX_NO_OLE_SUPPORT
  163. // allow hook to consume message
  164. if (m_pNotifyHook != NULL && m_pNotifyHook->OnPreTranslateMessage(pMsg))
  165. return TRUE;
  166. #endif
  167. if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
  168. {
  169. // finally, translate the message
  170. HACCEL hAccel = GetDefaultAccelerator();
  171. return hAccel != NULL && ::TranslateAccelerator(m_hWnd, hAccel, pMsg);
  172. }
  173. return FALSE;
  174. }
  175. void CFrameWnd::PostNcDestroy()
  176. {
  177. // default for frame windows is to allocate them on the heap
  178. // the default post-cleanup is to 'delete this'.
  179. // never explicitly call 'delete' on a CFrameWnd, use DestroyWindow instead
  180. delete this;
  181. }
  182. void CFrameWnd::OnPaletteChanged(CWnd* pFocusWnd)
  183. {
  184. CWnd::OnPaletteChanged(pFocusWnd);
  185. #ifndef _AFX_NO_OLE_SUPPORT
  186. if (m_pNotifyHook != NULL)
  187. m_pNotifyHook->OnPaletteChanged(pFocusWnd);
  188. #endif
  189. }
  190. BOOL CFrameWnd::OnQueryNewPalette()
  191. {
  192. #ifndef _AFX_NO_OLE_SUPPORT
  193. if (m_pNotifyHook != NULL && m_pNotifyHook->OnQueryNewPalette())
  194. return TRUE;
  195. #endif
  196. return CWnd::OnQueryNewPalette();
  197. }
  198. /////////////////////////////////////////////////////////////////////////////
  199. // CFrameWnd support for context sensitive help.
  200. void CFrameWnd::ExitHelpMode()
  201. {
  202. // if not in help mode currently, this is a no-op
  203. if (!m_bHelpMode)
  204. return;
  205. // only post new WM_EXITHELPMODE message if one doesn't already exist
  206. // in the queue.
  207. MSG msg;
  208. if (!::PeekMessage(&msg, m_hWnd, WM_EXITHELPMODE, WM_EXITHELPMODE,
  209. PM_REMOVE|PM_NOYIELD))
  210. {
  211. VERIFY(::PostMessage(m_hWnd, WM_EXITHELPMODE, 0, 0));
  212. }
  213. // release capture if this window has it
  214. if (::GetCapture() == m_hWnd)
  215. ReleaseCapture();
  216. CFrameWnd* pFrameWnd = GetTopLevelFrame();
  217. ASSERT_VALID(pFrameWnd);
  218. pFrameWnd->m_bHelpMode = m_bHelpMode = HELP_INACTIVE;
  219. PostMessage(WM_KICKIDLE); // trigger idle update
  220. }
  221. BOOL CFrameWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  222. {
  223. CFrameWnd* pFrameWnd = GetTopLevelFrame();
  224. ASSERT_VALID(pFrameWnd);
  225. if (pFrameWnd->m_bHelpMode)
  226. {
  227. SetCursor(afxData.hcurHelp);
  228. return TRUE;
  229. }
  230. return CWnd::OnSetCursor(pWnd, nHitTest, message);
  231. }
  232. LRESULT CFrameWnd::OnCommandHelp(WPARAM, LPARAM lParam)
  233. {
  234. if (lParam == 0)
  235. {
  236. if (IsTracking())
  237. lParam = HID_BASE_COMMAND+m_nIDTracking;
  238. else
  239. lParam = HID_BASE_RESOURCE+m_nIDHelp;
  240. }
  241. if (lParam != 0)
  242. {
  243. CWinApp* pApp = AfxGetApp();
  244. if (pApp != NULL)
  245. pApp->WinHelp(lParam);
  246. return TRUE;
  247. }
  248. return FALSE;
  249. }
  250. LRESULT CFrameWnd::OnHelpHitTest(WPARAM, LPARAM)
  251. {
  252. if (m_nIDHelp != 0)
  253. return HID_BASE_RESOURCE+m_nIDHelp;
  254. else
  255. return 0;
  256. }
  257. BOOL CFrameWnd::OnCommand(WPARAM wParam, LPARAM lParam)
  258. // return TRUE if command invocation was attempted
  259. {
  260. HWND hWndCtrl = (HWND)lParam;
  261. UINT nID = LOWORD(wParam);
  262. CFrameWnd* pFrameWnd = GetTopLevelFrame();
  263. ASSERT_VALID(pFrameWnd);
  264. if (pFrameWnd->m_bHelpMode && hWndCtrl == NULL &&
  265. nID != ID_HELP && nID != ID_DEFAULT_HELP && nID != ID_CONTEXT_HELP)
  266. {
  267. // route as help
  268. if (!SendMessage(WM_COMMANDHELP, 0, HID_BASE_COMMAND+nID))
  269. SendMessage(WM_COMMAND, ID_DEFAULT_HELP);
  270. return TRUE;
  271. }
  272. // route as normal command
  273. return CWnd::OnCommand(wParam, lParam);
  274. }
  275. /////////////////////////////////////////////////////////////////////////////
  276. // CFrameWnd support for modality
  277. BOOL AFXAPI AfxIsDescendant(HWND hWndParent, HWND hWndChild)
  278. // helper for detecting whether child descendent of parent
  279. // (works with owned popups as well)
  280. {
  281. ASSERT(::IsWindow(hWndParent));
  282. ASSERT(::IsWindow(hWndChild));
  283. do
  284. {
  285. if (hWndParent == hWndChild)
  286. return TRUE;
  287. hWndChild = AfxGetParentOwner(hWndChild);
  288. } while (hWndChild != NULL);
  289. return FALSE;
  290. }
  291. void CFrameWnd::BeginModalState()
  292. {
  293. ASSERT(m_hWnd != NULL);
  294. ASSERT(::IsWindow(m_hWnd));
  295. // allow stacking, but don't do anything
  296. if (++m_cModalStack > 1)
  297. return;
  298. // determine top-level parent, since that is the true parent of any
  299. // modeless windows anyway...
  300. CWnd* pParent = GetTopLevelParent();
  301. // first count all windows that need to be disabled
  302. UINT nCount = 0;
  303. HWND hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
  304. while (hWnd != NULL)
  305. {
  306. if (::IsWindowEnabled(hWnd) &&
  307. CWnd::FromHandlePermanent(hWnd) != NULL &&
  308. AfxIsDescendant(pParent->m_hWnd, hWnd) &&
  309. ::SendMessage(hWnd, WM_DISABLEMODAL, 0, 0) == 0)
  310. {
  311. ++nCount;
  312. }
  313. hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
  314. }
  315. if (nCount == 0)
  316. return;
  317. m_phWndDisable = new HWND[nCount+1];
  318. // disable all windows connected to this frame (and add them to the list)
  319. UINT nIndex = 0;
  320. hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
  321. while (hWnd != NULL)
  322. {
  323. if (::IsWindowEnabled(hWnd) &&
  324. CWnd::FromHandlePermanent(hWnd) != NULL &&
  325. AfxIsDescendant(pParent->m_hWnd, hWnd) &&
  326. ::SendMessage(hWnd, WM_DISABLEMODAL, 0, 0) == 0)
  327. {
  328. ::EnableWindow(hWnd, FALSE);
  329. ASSERT(nIndex < nCount);
  330. m_phWndDisable[nIndex] = hWnd;
  331. ++nIndex;
  332. }
  333. hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
  334. }
  335. // terminate the list with a NULL
  336. ASSERT(nIndex < nCount+1);
  337. m_phWndDisable[nIndex] = NULL;
  338. }
  339. void CFrameWnd::EndModalState()
  340. {
  341. // pop one off the stack (don't undo modalness unless stack is down to zero)
  342. if (m_cModalStack == 0 || --m_cModalStack > 0 || m_phWndDisable == NULL)
  343. return;
  344. // enable all the windows disabled by BeginModalState
  345. ASSERT(m_phWndDisable != NULL);
  346. UINT nIndex = 0;
  347. while (m_phWndDisable[nIndex] != NULL)
  348. {
  349. ASSERT(m_phWndDisable[nIndex] != NULL);
  350. if (::IsWindow(m_phWndDisable[nIndex]))
  351. ::EnableWindow(m_phWndDisable[nIndex], TRUE);
  352. ++nIndex;
  353. }
  354. delete[] (void*)m_phWndDisable;
  355. m_phWndDisable = NULL;
  356. }
  357. void CFrameWnd::ShowOwnedWindows(BOOL bShow)
  358. {
  359. // walk through all top-level windows
  360. HWND hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
  361. while (hWnd != NULL)
  362. {
  363. CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
  364. if (pWnd != NULL && m_hWnd != hWnd && AfxIsDescendant(m_hWnd, hWnd))
  365. {
  366. DWORD dwStyle = ::GetWindowLong(hWnd, GWL_STYLE);
  367. if (!bShow && (dwStyle & (WS_VISIBLE|WS_DISABLED)) == WS_VISIBLE)
  368. {
  369. ::ShowWindow(hWnd, SW_HIDE);
  370. pWnd->m_nFlags |= WF_TEMPHIDE;
  371. }
  372. else if (bShow && (dwStyle & (WS_VISIBLE|WS_DISABLED)) == 0 &&
  373. (pWnd->m_nFlags & WF_TEMPHIDE))
  374. {
  375. ::ShowWindow(hWnd, SW_SHOWNOACTIVATE);
  376. pWnd->m_nFlags &= ~WF_TEMPHIDE;
  377. }
  378. }
  379. hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
  380. }
  381. }
  382. void CFrameWnd::OnEnable(BOOL bEnable)
  383. {
  384. if (bEnable && (m_nFlags & WF_STAYDISABLED))
  385. {
  386. // Work around for MAPI support. This makes sure the main window
  387. // remains disabled even when the mail system is booting.
  388. EnableWindow(FALSE);
  389. ::SetFocus(NULL);
  390. return;
  391. }
  392. // only for top-level (and non-owned) windows
  393. if (GetParent() != NULL)
  394. return;
  395. // this causes modal dialogs to be "truly modal"
  396. if (!bEnable && !InModalState())
  397. {
  398. ASSERT((m_nFlags & WF_MODALDISABLE) == 0);
  399. m_nFlags |= WF_MODALDISABLE;
  400. BeginModalState();
  401. }
  402. else if (bEnable && (m_nFlags & WF_MODALDISABLE))
  403. {
  404. m_nFlags &= ~WF_MODALDISABLE;
  405. EndModalState();
  406. // cause normal focus logic to kick in
  407. if (::GetActiveWindow() == m_hWnd)
  408. SendMessage(WM_ACTIVATE, WA_ACTIVE);
  409. }
  410. // force WM_NCACTIVATE because Windows may think it is unecessary
  411. if (bEnable && (m_nFlags & WF_STAYACTIVE))
  412. SendMessage(WM_NCACTIVATE, TRUE);
  413. // force WM_NCACTIVATE for floating windows too
  414. NotifyFloatingWindows(bEnable ? FS_ENABLE : FS_DISABLE);
  415. }
  416. void CFrameWnd::NotifyFloatingWindows(DWORD dwFlags)
  417. {
  418. ASSERT_VALID(this);
  419. ASSERT(m_hWnd != NULL);
  420. // get top level parent frame window first unless this is a child window
  421. CFrameWnd* pParent = (GetStyle() & WS_CHILD) ? this : GetTopLevelFrame();
  422. ASSERT(pParent != NULL);
  423. if (dwFlags & (FS_DEACTIVATE|FS_ACTIVATE))
  424. {
  425. // update parent window activation state
  426. BOOL bActivate = !(dwFlags & FS_DEACTIVATE);
  427. BOOL bEnabled = pParent->IsWindowEnabled();
  428. if (bActivate && bEnabled && pParent != this)
  429. {
  430. // Excel will try to Activate itself when it receives a
  431. // WM_NCACTIVATE so we need to keep it from doing that here.
  432. m_nFlags |= WF_KEEPMINIACTIVE;
  433. pParent->SendMessage(WM_NCACTIVATE, TRUE);
  434. m_nFlags &= ~WF_KEEPMINIACTIVE;
  435. }
  436. else
  437. {
  438. pParent->SendMessage(WM_NCACTIVATE, FALSE);
  439. }
  440. }
  441. // then update the state of all floating windows owned by the parent
  442. HWND hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
  443. while (hWnd != NULL)
  444. {
  445. if (AfxIsDescendant(pParent->m_hWnd, hWnd))
  446. ::SendMessage(hWnd, WM_FLOATSTATUS, dwFlags, 0);
  447. hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
  448. }
  449. }
  450. /////////////////////////////////////////////////////////////////////////////
  451. // CFrameWnd second phase creation
  452. BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
  453. {
  454. if (cs.lpszClass == NULL)
  455. {
  456. VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
  457. cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background
  458. }
  459. if ((cs.style & FWS_ADDTOTITLE) && afxData.bWin4)
  460. cs.style |= FWS_PREFIXTITLE;
  461. if (afxData.bWin4)
  462. cs.dwExStyle |= WS_EX_CLIENTEDGE;
  463. return TRUE;
  464. }
  465. BOOL CFrameWnd::Create(LPCTSTR lpszClassName,
  466. LPCTSTR lpszWindowName,
  467. DWORD dwStyle,
  468. const RECT& rect,
  469. CWnd* pParentWnd,
  470. LPCTSTR lpszMenuName,
  471. DWORD dwExStyle,
  472. CCreateContext* pContext)
  473. {
  474. HMENU hMenu = NULL;
  475. if (lpszMenuName != NULL)
  476. {
  477. // load in a menu that will get destroyed when window gets destroyed
  478. HINSTANCE hInst = AfxFindResourceHandle(lpszMenuName, RT_MENU);
  479. if ((hMenu = ::LoadMenu(hInst, lpszMenuName)) == NULL)
  480. {
  481. TRACE0("Warning: failed to load menu for CFrameWnd.\n");
  482. PostNcDestroy(); // perhaps delete the C++ object
  483. return FALSE;
  484. }
  485. }
  486. m_strTitle = lpszWindowName; // save title for later
  487. if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
  488. rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
  489. pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext))
  490. {
  491. TRACE0("Warning: failed to create CFrameWnd.\n");
  492. if (hMenu != NULL)
  493. DestroyMenu(hMenu);
  494. return FALSE;
  495. }
  496. return TRUE;
  497. }
  498. CWnd* CFrameWnd::CreateView(CCreateContext* pContext, UINT nID)
  499. {
  500. ASSERT(m_hWnd != NULL);
  501. ASSERT(::IsWindow(m_hWnd));
  502. ASSERT(pContext != NULL);
  503. ASSERT(pContext->m_pNewViewClass != NULL);
  504. // Note: can be a CWnd with PostNcDestroy self cleanup
  505. CWnd* pView = (CWnd*)pContext->m_pNewViewClass->CreateObject();
  506. if (pView == NULL)
  507. {
  508. TRACE1("Warning: Dynamic create of view type %hs failed.\n",
  509. pContext->m_pNewViewClass->m_lpszClassName);
  510. return NULL;
  511. }
  512. ASSERT_KINDOF(CWnd, pView);
  513. // views are always created with a border!
  514. if (!pView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
  515. CRect(0,0,0,0), this, nID, pContext))
  516. {
  517. TRACE0("Warning: could not create view for frame.\n");
  518. return NULL; // can't continue without a view
  519. }
  520. if (afxData.bWin4 && (pView->GetExStyle() & WS_EX_CLIENTEDGE))
  521. {
  522. // remove the 3d style from the frame, since the view is
  523. // providing it.
  524. // make sure to recalc the non-client area
  525. ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_FRAMECHANGED);
  526. }
  527. return pView;
  528. }
  529. BOOL CFrameWnd::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext)
  530. {
  531. // default create client will create a view if asked for it
  532. if (pContext != NULL && pContext->m_pNewViewClass != NULL)
  533. {
  534. if (CreateView(pContext, AFX_IDW_PANE_FIRST) == NULL)
  535. return FALSE;
  536. }
  537. return TRUE;
  538. }
  539. int CFrameWnd::OnCreate(LPCREATESTRUCT lpcs)
  540. {
  541. CCreateContext* pContext = (CCreateContext*)lpcs->lpCreateParams;
  542. return OnCreateHelper(lpcs, pContext);
  543. }
  544. int CFrameWnd::OnCreateHelper(LPCREATESTRUCT lpcs, CCreateContext* pContext)
  545. {
  546. if (CWnd::OnCreate(lpcs) == -1)
  547. return -1;
  548. // create special children first
  549. if (!OnCreateClient(lpcs, pContext))
  550. {
  551. TRACE0("Failed to create client pane/view for frame.\n");
  552. return -1;
  553. }
  554. // post message for initial message string
  555. PostMessage(WM_SETMESSAGESTRING, AFX_IDS_IDLEMESSAGE);
  556. // make sure the child windows have been properly sized
  557. RecalcLayout();
  558. return 0; // create ok
  559. }
  560. LPCTSTR CFrameWnd::GetIconWndClass(DWORD dwDefaultStyle, UINT nIDResource)
  561. {
  562. ASSERT_VALID_IDR(nIDResource);
  563. HINSTANCE hInst = AfxFindResourceHandle(
  564. MAKEINTRESOURCE(nIDResource), RT_GROUP_ICON);
  565. HICON hIcon = ::LoadIcon(hInst, MAKEINTRESOURCE(nIDResource));
  566. if (hIcon != NULL)
  567. {
  568. CREATESTRUCT cs;
  569. memset(&cs, 0, sizeof(CREATESTRUCT));
  570. cs.style = dwDefaultStyle;
  571. PreCreateWindow(cs);
  572. // will fill lpszClassName with default WNDCLASS name
  573. // ignore instance handle from PreCreateWindow.
  574. WNDCLASS wndcls;
  575. if (cs.lpszClass != NULL &&
  576. GetClassInfo(AfxGetInstanceHandle(), cs.lpszClass, &wndcls) &&
  577. wndcls.hIcon != hIcon)
  578. {
  579. // register a very similar WNDCLASS
  580. return AfxRegisterWndClass(wndcls.style,
  581. wndcls.hCursor, wndcls.hbrBackground, hIcon);
  582. }
  583. }
  584. return NULL; // just use the default
  585. }
  586. BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
  587. CWnd* pParentWnd, CCreateContext* pContext)
  588. {
  589. // only do this once
  590. ASSERT_VALID_IDR(nIDResource);
  591. ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);
  592. m_nIDHelp = nIDResource; // ID for help context (+HID_BASE_RESOURCE)
  593. CString strFullString;
  594. if (strFullString.LoadString(nIDResource))
  595. AfxExtractSubString(m_strTitle, strFullString, 0); // first sub-string
  596. VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
  597. // attempt to create the window
  598. LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);
  599. LPCTSTR lpszTitle = m_strTitle;
  600. if (!Create(lpszClass, lpszTitle, dwDefaultStyle, rectDefault,
  601. pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext))
  602. {
  603. return FALSE; // will self destruct on failure normally
  604. }
  605. // save the default menu handle
  606. ASSERT(m_hWnd != NULL);
  607. m_hMenuDefault = ::GetMenu(m_hWnd);
  608. // load accelerator resource
  609. LoadAccelTable(MAKEINTRESOURCE(nIDResource));
  610. if (pContext == NULL) // send initial update
  611. SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);
  612. return TRUE;
  613. }
  614. void CFrameWnd::OnUpdateFrameMenu(HMENU hMenuAlt)
  615. {
  616. if (hMenuAlt == NULL)
  617. {
  618. // attempt to get default menu from document
  619. CDocument* pDoc = GetActiveDocument();
  620. if (pDoc != NULL)
  621. hMenuAlt = pDoc->GetDefaultMenu();
  622. // use default menu stored in frame if none from document
  623. if (hMenuAlt == NULL)
  624. hMenuAlt = m_hMenuDefault;
  625. }
  626. // finally, set the menu
  627. ::SetMenu(m_hWnd, hMenuAlt);
  628. }
  629. void CFrameWnd::InitialUpdateFrame(CDocument* pDoc, BOOL bMakeVisible)
  630. {
  631. // if the frame does not have an active view, set to first pane
  632. CView* pView = NULL;
  633. if (GetActiveView() == NULL)
  634. {
  635. CWnd* pWnd = GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);
  636. if (pWnd != NULL && pWnd->IsKindOf(RUNTIME_CLASS(CView)))
  637. {
  638. pView = (CView*)pWnd;
  639. SetActiveView(pView, FALSE);
  640. }
  641. }
  642. if (bMakeVisible)
  643. {
  644. // send initial update to all views (and other controls) in the frame
  645. SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);
  646. // give view a chance to save the focus (CFormView needs this)
  647. if (pView != NULL)
  648. pView->OnActivateFrame(WA_INACTIVE, this);
  649. // finally, activate the frame
  650. // (send the default show command unless the main desktop window)
  651. int nCmdShow = -1; // default
  652. CWinApp* pApp = AfxGetApp();
  653. if (pApp != NULL && pApp->m_pMainWnd == this)
  654. {
  655. nCmdShow = pApp->m_nCmdShow; // use the parameter from WinMain
  656. pApp->m_nCmdShow = -1; // set to default after first time
  657. }
  658. ActivateFrame(nCmdShow);
  659. if (pView != NULL)
  660. pView->OnActivateView(TRUE, pView, pView);
  661. }
  662. // update frame counts and frame title (may already have been visible)
  663. if (pDoc != NULL)
  664. pDoc->UpdateFrameCounts();
  665. OnUpdateFrameTitle(TRUE);
  666. }
  667. /////////////////////////////////////////////////////////////////////////////
  668. // CFrameWnd closing down
  669. void CFrameWnd::OnClose()
  670. {
  671. if (m_lpfnCloseProc != NULL && !(*m_lpfnCloseProc)(this))
  672. return;
  673. // Note: only queries the active document
  674. CDocument* pDocument = GetActiveDocument();
  675. if (pDocument != NULL && !pDocument->CanCloseFrame(this))
  676. {
  677. // document can't close right now -- don't close it
  678. return;
  679. }
  680. CWinApp* pApp = AfxGetApp();
  681. if (pApp != NULL && pApp->m_pMainWnd == this)
  682. {
  683. // attempt to save all documents
  684. if (pDocument == NULL && !pApp->SaveAllModified())
  685. return; // don't close it
  686. // hide the application's windows before closing all the documents
  687. pApp->HideApplication();
  688. // close all documents first
  689. pApp->CloseAllDocuments(FALSE);
  690. // don't exit if there are outstanding component objects
  691. if (!AfxOleCanExitApp())
  692. {
  693. // take user out of control of the app
  694. AfxOleSetUserCtrl(FALSE);
  695. // don't destroy the main window and close down just yet
  696. // (there are outstanding component (OLE) objects)
  697. return;
  698. }
  699. // there are cases where destroying the documents may destroy the
  700. // main window of the application.
  701. if (!afxContextIsDLL && pApp->m_pMainWnd == NULL)
  702. {
  703. AfxPostQuitMessage(0);
  704. return;
  705. }
  706. }
  707. // detect the case that this is the last frame on the document and
  708. // shut down with OnCloseDocument instead.
  709. if (pDocument != NULL && pDocument->m_bAutoDelete)
  710. {
  711. BOOL bOtherFrame = FALSE;
  712. POSITION pos = pDocument->GetFirstViewPosition();
  713. while (pos != NULL)
  714. {
  715. CView* pView = pDocument->GetNextView(pos);
  716. ASSERT_VALID(pView);
  717. if (pView->GetParentFrame() != this)
  718. {
  719. bOtherFrame = TRUE;
  720. break;
  721. }
  722. }
  723. if (!bOtherFrame)
  724. {
  725. pDocument->OnCloseDocument();
  726. return;
  727. }
  728. // allow the document to cleanup before the window is destroyed
  729. pDocument->PreCloseFrame(this);
  730. }
  731. // then destroy the window
  732. DestroyWindow();
  733. }
  734. void CFrameWnd::OnDestroy()
  735. {
  736. DestroyDockBars();
  737. // reset menu to default before final shutdown
  738. if (m_hMenuDefault != NULL && ::GetMenu(m_hWnd) != m_hMenuDefault)
  739. {
  740. ::SetMenu(m_hWnd, m_hMenuDefault);
  741. ASSERT(::GetMenu(m_hWnd) == m_hMenuDefault);
  742. }
  743. // Automatically quit when the main window is destroyed.
  744. CWinApp* pApp = AfxGetApp();
  745. if (pApp != NULL && pApp->m_pMainWnd == this)
  746. {
  747. // closing the main application window
  748. ::WinHelp(m_hWnd, NULL, HELP_QUIT, 0L);
  749. // will call PostQuitMessage in CWnd::OnNcDestroy
  750. }
  751. CWnd::OnDestroy();
  752. }
  753. void CFrameWnd::RemoveControlBar(CControlBar *pBar)
  754. {
  755. POSITION pos = m_listControlBars.Find(pBar);
  756. if (pos != NULL)
  757. m_listControlBars.RemoveAt(pos);
  758. }
  759. /////////////////////////////////////////////////////////////////////////////
  760. // CFrameWnd command/message routing
  761. BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra,
  762. AFX_CMDHANDLERINFO* pHandlerInfo)
  763. {
  764. CPushRoutingFrame push(this);
  765. // pump through current view FIRST
  766. CView* pView = GetActiveView();
  767. if (pView != NULL && pView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
  768. return TRUE;
  769. // then pump through frame
  770. if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
  771. return TRUE;
  772. // last but not least, pump through app
  773. CWinApp* pApp = AfxGetApp();
  774. if (pApp != NULL && pApp->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
  775. return TRUE;
  776. return FALSE;
  777. }
  778. // Delegate scroll messages to active view as well
  779. void CFrameWnd::OnHScroll(UINT, UINT, CScrollBar*)
  780. {
  781. CWnd* pActiveView = GetActiveView();
  782. if (pActiveView != NULL)
  783. {
  784. const MSG* pMsg = GetCurrentMessage();
  785. pActiveView->SendMessage(WM_HSCROLL, pMsg->wParam, pMsg->lParam);
  786. }
  787. }
  788. void CFrameWnd::OnVScroll(UINT, UINT, CScrollBar*)
  789. {
  790. CWnd* pActiveView = GetActiveView();
  791. if (pActiveView != NULL)
  792. {
  793. const MSG* pMsg = GetCurrentMessage();
  794. pActiveView->SendMessage(WM_VSCROLL, pMsg->wParam, pMsg->lParam);
  795. }
  796. }
  797. LRESULT CFrameWnd::OnActivateTopLevel(WPARAM wParam, LPARAM lParam)
  798. {
  799. CWnd::OnActivateTopLevel(wParam, lParam);
  800. // exit Shift+F1 help mode on activation changes
  801. ExitHelpMode();
  802. #ifndef _AFX_NO_OLE_SUPPORT
  803. // allow OnFrameWindowActivate to be sent to in-place items
  804. if (m_pNotifyHook != NULL)
  805. {
  806. // activate when active and when not minimized
  807. m_pNotifyHook->OnActivate(
  808. LOWORD(wParam) != WA_INACTIVE && !HIWORD(wParam));
  809. }
  810. #endif
  811. // deactivate current active view
  812. if (AfxGetThread()->m_pMainWnd == this)
  813. {
  814. CView* pActiveView = GetActiveView();
  815. if (pActiveView == NULL)
  816. pActiveView = GetActiveFrame()->GetActiveView();
  817. if (pActiveView != NULL)
  818. pActiveView->OnActivateView(FALSE, pActiveView, pActiveView);
  819. }
  820. // force idle processing to update any key state indicators
  821. PostMessage(WM_KICKIDLE);
  822. return 0;
  823. }
  824. void CFrameWnd::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
  825. {
  826. CWnd::OnActivate(nState, pWndOther, bMinimized);
  827. // get top level frame unless this is a child window
  828. // determine if window should be active or not
  829. CFrameWnd* pTopLevel = (GetStyle() & WS_CHILD) ? this : GetTopLevelFrame();
  830. ASSERT(pTopLevel != NULL);
  831. CWnd* pActive = (nState == WA_INACTIVE ? pWndOther : this);
  832. BOOL bStayActive =
  833. (pTopLevel == pActive ||
  834. (pTopLevel == pActive->GetTopLevelFrame() &&
  835. (pActive == pTopLevel ||
  836. pActive->SendMessage(WM_FLOATSTATUS, FS_SYNCACTIVE) != 0)));
  837. pTopLevel->m_nFlags &= ~WF_STAYACTIVE;
  838. if (bStayActive)
  839. pTopLevel->m_nFlags |= WF_STAYACTIVE;
  840. // sync floating windows to the new state
  841. NotifyFloatingWindows(bStayActive ? FS_ACTIVATE : FS_DEACTIVATE);
  842. // get active view (use active frame if no active view)
  843. CView* pActiveView = GetActiveView();
  844. if (pActiveView == NULL)
  845. pActiveView = GetActiveFrame()->GetActiveView();
  846. // when frame gets activated, re-activate current view
  847. if (pActiveView != NULL)
  848. {
  849. if (nState != WA_INACTIVE && !bMinimized)
  850. pActiveView->OnActivateView(TRUE, pActiveView, pActiveView);
  851. // always notify the view of frame activations
  852. pActiveView->OnActivateFrame(nState, this);
  853. }
  854. }
  855. BOOL CFrameWnd::OnNcActivate(BOOL bActive)
  856. {
  857. // stay active if WF_STAYACTIVE bit is on
  858. if (m_nFlags & WF_STAYACTIVE)
  859. bActive = TRUE;
  860. // but do not stay active if the window is disabled
  861. if (!IsWindowEnabled())
  862. bActive = FALSE;
  863. // do not call the base class because it will call Default()
  864. // and we may have changed bActive.
  865. return (BOOL)DefWindowProc(WM_NCACTIVATE, bActive, 0L);
  866. }
  867. void CFrameWnd::OnSysCommand(UINT nID, LONG lParam)
  868. {
  869. CFrameWnd* pFrameWnd = GetTopLevelFrame();
  870. ASSERT_VALID(pFrameWnd);
  871. // set status bar as appropriate
  872. UINT nItemID = (nID & 0xFFF0);
  873. // don't interfere with system commands if not in help mode
  874. if (pFrameWnd->m_bHelpMode)
  875. {
  876. switch (nItemID)
  877. {
  878. case SC_SIZE:
  879. case SC_MOVE:
  880. case SC_MINIMIZE:
  881. case SC_MAXIMIZE:
  882. case SC_NEXTWINDOW:
  883. case SC_PREVWINDOW:
  884. case SC_CLOSE:
  885. case SC_RESTORE:
  886. case SC_TASKLIST:
  887. if (!SendMessage(WM_COMMANDHELP, 0,
  888. HID_BASE_COMMAND+ID_COMMAND_FROM_SC(nItemID)))
  889. SendMessage(WM_COMMAND, ID_DEFAULT_HELP);
  890. return;
  891. }
  892. }
  893. // call default functionality
  894. CWnd::OnSysCommand(nID, lParam);
  895. }
  896. /////////////////////////////////////////////////////////////////////////////
  897. // default frame processing
  898. // default drop processing will attempt to open the file
  899. void CFrameWnd::OnDropFiles(HDROP hDropInfo)
  900. {
  901. SetActiveWindow(); // activate us first !
  902. UINT nFiles = ::DragQueryFile(hDropInfo, (UINT)-1, NULL, 0);
  903. CWinApp* pApp = AfxGetApp();
  904. ASSERT(pApp != NULL);
  905. for (UINT iFile = 0; iFile < nFiles; iFile++)
  906. {
  907. TCHAR szFileName[_MAX_PATH];
  908. ::DragQueryFile(hDropInfo, iFile, szFileName, _MAX_PATH);
  909. pApp->OpenDocumentFile(szFileName);
  910. }
  911. ::DragFinish(hDropInfo);
  912. }
  913. // query end session for main frame will attempt to close it all down
  914. BOOL CFrameWnd::OnQueryEndSession()
  915. {
  916. CWinApp* pApp = AfxGetApp();
  917. if (pApp != NULL && pApp->m_pMainWnd == this)
  918. return pApp->SaveAllModified();
  919. return TRUE;
  920. }
  921. // when Windows session ends, close all documents
  922. void CFrameWnd::OnEndSession(BOOL bEnding)
  923. {
  924. if (!bEnding)
  925. return;
  926. CWinApp* pApp = AfxGetApp();
  927. if (pApp != NULL && pApp->m_pMainWnd == this)
  928. {
  929. AfxOleSetUserCtrl(TRUE); // keeps from randomly shutting down
  930. pApp->CloseAllDocuments(TRUE);
  931. // allow application to save settings, etc.
  932. pApp->ExitInstance();
  933. }
  934. }
  935. /////////////////////////////////////////////////////////////////////////////
  936. // Support for Shell DDE Execute messages
  937. LRESULT CFrameWnd::OnDDEInitiate(WPARAM wParam, LPARAM lParam)
  938. {
  939. CWinApp* pApp = AfxGetApp();
  940. if (pApp != NULL &&
  941. LOWORD(lParam) != 0 && HIWORD(lParam) != 0 &&
  942. (ATOM)LOWORD(lParam) == pApp->m_atomApp &&
  943. (ATOM)HIWORD(lParam) == pApp->m_atomSystemTopic)
  944. {
  945. // make duplicates of the incoming atoms (really adding a reference)
  946. TCHAR szAtomName[_MAX_PATH];
  947. VERIFY(GlobalGetAtomName(pApp->m_atomApp,
  948. szAtomName, _MAX_PATH - 1) != 0);
  949. VERIFY(GlobalAddAtom(szAtomName) == pApp->m_atomApp);
  950. VERIFY(GlobalGetAtomName(pApp->m_atomSystemTopic,
  951. szAtomName, _MAX_PATH - 1) != 0);
  952. VERIFY(GlobalAddAtom(szAtomName) == pApp->m_atomSystemTopic);
  953. // send the WM_DDE_ACK (caller will delete duplicate atoms)
  954. ::SendMessage((HWND)wParam, WM_DDE_ACK, (WPARAM)m_hWnd,
  955. MAKELPARAM(pApp->m_atomApp, pApp->m_atomSystemTopic));
  956. }
  957. return 0L;
  958. }
  959. // always ACK the execute command - even if we do nothing
  960. LRESULT CFrameWnd::OnDDEExecute(WPARAM wParam, LPARAM lParam)
  961. {
  962. // unpack the DDE message
  963. UINT unused;
  964. HGLOBAL hData;
  965. VERIFY(UnpackDDElParam(WM_DDE_EXECUTE, lParam, &unused, (UINT*)&hData));
  966. // get the command string
  967. TCHAR szCommand[_MAX_PATH * 2];
  968. LPCTSTR lpsz = (LPCTSTR)GlobalLock(hData);
  969. lstrcpyn(szCommand, lpsz, _countof(szCommand));
  970. GlobalUnlock(hData);
  971. // acknowledge now - before attempting to execute
  972. ::PostMessage((HWND)wParam, WM_DDE_ACK, (WPARAM)m_hWnd,
  973. ReuseDDElParam(lParam, WM_DDE_EXECUTE, WM_DDE_ACK,
  974. (UINT)0x8000, (UINT)hData));
  975. // don't execute the command when the window is disabled
  976. if (!IsWindowEnabled())
  977. {
  978. TRACE1("Warning: DDE command '%s' ignored because window is disabled.\n",
  979. szCommand);
  980. return 0;
  981. }
  982. // execute the command
  983. if (!AfxGetApp()->OnDDECommand(szCommand))
  984. TRACE1("Error: failed to execute DDE command '%s'.\n", szCommand);
  985. return 0L;
  986. }
  987. LRESULT CFrameWnd::OnDDETerminate(WPARAM wParam, LPARAM lParam)
  988. {
  989. ::PostMessage((HWND)wParam, WM_DDE_TERMINATE, (WPARAM)m_hWnd, lParam);
  990. return 0L;
  991. }
  992. /////////////////////////////////////////////////////////////////////////////
  993. // CFrameWnd attributes
  994. CView* CFrameWnd::GetActiveView() const
  995. {
  996. ASSERT(m_pViewActive == NULL ||
  997. m_pViewActive->IsKindOf(RUNTIME_CLASS(CView)));
  998. return m_pViewActive;
  999. }
  1000. void CFrameWnd::SetActiveView(CView* pViewNew, BOOL bNotify)
  1001. {
  1002. #ifdef _DEBUG
  1003. if (pViewNew != NULL)
  1004. {
  1005. ASSERT(IsChild(pViewNew));
  1006. ASSERT_KINDOF(CView, pViewNew);
  1007. }
  1008. #endif //_DEBUG
  1009. CView* pViewOld = m_pViewActive;
  1010. if (pViewNew == pViewOld)
  1011. return; // do not re-activate if SetActiveView called more than once
  1012. m_pViewActive = NULL; // no active for the following processing
  1013. // deactivate the old one
  1014. if (pViewOld != NULL)
  1015. pViewOld->OnActivateView(FALSE, pViewNew, pViewOld);
  1016. // if the OnActivateView moves the active window,
  1017. // that will veto this change
  1018. if (m_pViewActive != NULL)
  1019. return; // already set
  1020. m_pViewActive = pViewNew;
  1021. // activate
  1022. if (pViewNew != NULL && bNotify)
  1023. pViewNew->OnActivateView(TRUE, pViewNew, pViewOld);
  1024. }
  1025. /////////////////////////////////////////////////////////////////////////////
  1026. // Special view swapping/activation
  1027. void CFrameWnd::OnSetFocus(CWnd* pOldWnd)
  1028. {
  1029. if (m_pViewActive != NULL)
  1030. m_pViewActive->SetFocus();
  1031. else
  1032. CWnd::OnSetFocus(pOldWnd);
  1033. }
  1034. CDocument* CFrameWnd::GetActiveDocument()
  1035. {
  1036. ASSERT_VALID(this);
  1037. CView* pView = GetActiveView();
  1038. if (pView != NULL)
  1039. return pView->GetDocument();
  1040. return NULL;
  1041. }
  1042. void CFrameWnd::ShowControlBar(CControlBar* pBar, BOOL bShow, BOOL bDelay)
  1043. {
  1044. ASSERT(pBar != NULL);
  1045. CFrameWnd* pParentFrame = pBar->GetDockingFrame();
  1046. ASSERT(pParentFrame->GetTopLevelParent() == GetTopLevelParent());
  1047. // parent frame of bar must be related
  1048. if (bDelay)
  1049. {
  1050. pBar->DelayShow(bShow);
  1051. pParentFrame->DelayRecalcLayout();
  1052. }
  1053. else
  1054. {
  1055. pBar->SetWindowPos(NULL, 0, 0, 0, 0,
  1056. SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|
  1057. (bShow ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
  1058. // call DelayShow to clear any contradictory DelayShow
  1059. pBar->DelayShow(bShow);
  1060. if (bShow || !pBar->IsFloating())
  1061. pParentFrame->RecalcLayout(FALSE);
  1062. }
  1063. // show or hide the floating frame as appropriate
  1064. if (pBar->IsFloating())
  1065. {
  1066. int nVisCount = pBar->m_pDockBar != NULL ?
  1067. pBar->m_pDockBar->GetDockedVisibleCount() : bShow ? 1 : 0;
  1068. if (nVisCount == 1 && bShow)
  1069. {
  1070. pParentFrame->m_nShowDelay = -1;
  1071. if (bDelay)
  1072. {
  1073. pParentFrame->m_nShowDelay = SW_SHOWNA;
  1074. pParentFrame->RecalcLayout(FALSE);
  1075. }
  1076. else
  1077. pParentFrame->ShowWindow(SW_SHOWNA);
  1078. }
  1079. else if (nVisCount == 0)
  1080. {
  1081. ASSERT(!bShow);
  1082. pParentFrame->m_nShowDelay = -1;
  1083. if (bDelay)
  1084. pParentFrame->m_nShowDelay = SW_HIDE;
  1085. else
  1086. pParentFrame->ShowWindow(SW_HIDE);
  1087. }
  1088. else if (!bDelay)
  1089. {
  1090. pParentFrame->RecalcLayout(FALSE);
  1091. }
  1092. }
  1093. }
  1094. /////////////////////////////////////////////////////////////////////////////
  1095. // Command prompts
  1096. void CFrameWnd::OnInitMenu(CMenu* pMenu)
  1097. {
  1098. #ifndef _AFX_NO_OLE_SUPPORT
  1099. // allow hook to consume message
  1100. if (m_pNotifyHook != NULL)
  1101. {
  1102. #ifdef _AFXDLL
  1103. ASSERT(m_pModuleState != NULL);
  1104. if (m_pModuleState->m_dwVersion >= 0x423)
  1105. #endif
  1106. m_pNotifyHook->OnInitMenu(pMenu);
  1107. #endif
  1108. }
  1109. Default();
  1110. }
  1111. void CFrameWnd::OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu)
  1112. {
  1113. AfxCancelModes(m_hWnd);
  1114. if (bSysMenu)
  1115. return; // don't support system menu
  1116. #ifndef _AFX_NO_OLE_SUPPORT
  1117. // allow hook to consume message
  1118. if (m_pNotifyHook != NULL)
  1119. {
  1120. #ifdef _AFXDLL
  1121. ASSERT(m_pModuleState != NULL);
  1122. if (m_pModuleState->m_dwVersion >= 0x423)
  1123. #endif
  1124. if (m_pNotifyHook->OnInitMenuPopup(pMenu, nIndex, bSysMenu))
  1125. return;
  1126. }
  1127. #endif
  1128. ASSERT(pMenu != NULL);
  1129. // check the enabled state of various menu items
  1130. CCmdUI state;
  1131. state.m_pMenu = pMenu;
  1132. ASSERT(state.m_pOther == NULL);
  1133. ASSERT(state.m_pParentMenu == NULL);
  1134. // determine if menu is popup in top-level menu and set m_pOther to
  1135. // it if so (m_pParentMenu == NULL indicates that it is secondary popup)
  1136. HMENU hParentMenu;
  1137. if (AfxGetThreadState()->m_hTrackingMenu == pMenu->m_hMenu)
  1138. state.m_pParentMenu = pMenu; // parent == child for tracking popup
  1139. else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL)
  1140. {
  1141. CWnd* pParent = GetTopLevelParent();
  1142. // child windows don't have menus -- need to go to the top!
  1143. if (pParent != NULL &&
  1144. (hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL)
  1145. {
  1146. int nIndexMax = ::GetMenuItemCount(hParentMenu);
  1147. for (int nIndex = 0; nIndex < nIndexMax; nIndex++)
  1148. {
  1149. if (::GetSubMenu(hParentMenu, nIndex) == pMenu->m_hMenu)
  1150. {
  1151. // when popup is found, m_pParentMenu is containing menu
  1152. state.m_pParentMenu = CMenu::FromHandle(hParentMenu);
  1153. break;
  1154. }
  1155. }
  1156. }
  1157. }
  1158. state.m_nIndexMax = pMenu->GetMenuItemCount();
  1159. for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;
  1160. state.m_nIndex++)
  1161. {
  1162. state.m_nID = pMenu->GetMenuItemID(state.m_nIndex);
  1163. if (state.m_nID == 0)
  1164. continue; // menu separator or invalid cmd - ignore it
  1165. ASSERT(state.m_pOther == NULL);
  1166. ASSERT(state.m_pMenu != NULL);
  1167. if (state.m_nID == (UINT)-1)
  1168. {
  1169. // possibly a popup menu, route to first item of that popup
  1170. state.m_pSubMenu = pMenu->GetSubMenu(state.m_nIndex);
  1171. if (state.m_pSubMenu == NULL ||
  1172. (state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 ||
  1173. state.m_nID == (UINT)-1)
  1174. {
  1175. continue; // first item of popup can't be routed to
  1176. }
  1177. state.DoUpdate(this, FALSE); // popups are never auto disabled
  1178. }
  1179. else
  1180. {
  1181. // normal menu item
  1182. // Auto enable/disable if frame window has 'm_bAutoMenuEnable'
  1183. // set and command is _not_ a system command.
  1184. state.m_pSubMenu = NULL;
  1185. state.DoUpdate(this, m_bAutoMenuEnable && state.m_nID < 0xF000);
  1186. }
  1187. // adjust for menu deletions and additions
  1188. UINT nCount = pMenu->GetMenuItemCount();
  1189. if (nCount < state.m_nIndexMax)
  1190. {
  1191. state.m_nIndex -= (state.m_nIndexMax - nCount);
  1192. while (state.m_nIndex < nCount &&
  1193. pMenu->GetMenuItemID(state.m_nIndex) == state.m_nID)
  1194. {
  1195. state.m_nIndex++;
  1196. }
  1197. }
  1198. state.m_nIndexMax = nCount;
  1199. }
  1200. }
  1201. void CFrameWnd::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu)
  1202. {
  1203. CFrameWnd* pFrameWnd = GetTopLevelFrame();
  1204. ASSERT_VALID(pFrameWnd);
  1205. #ifndef _AFX_NO_OLE_SUPPORT
  1206. // allow hook to consume message
  1207. if (m_pNotifyHook != NULL)
  1208. {
  1209. #ifdef _AFXDLL
  1210. ASSERT(m_pModuleState != NULL);
  1211. if (m_pModuleState->m_dwVersion >= 0x423)
  1212. #endif
  1213. if (m_pNotifyHook->OnMenuSelect(nItemID, nFlags, hSysMenu))
  1214. return;
  1215. }
  1216. #endif
  1217. // set the tracking state (update on idle)
  1218. if (nFlags == 0xFFFF)
  1219. {
  1220. // cancel menu operation (go back to idle now)
  1221. m_nFlags &= ~WF_NOPOPMSG;
  1222. if (!pFrameWnd->m_bHelpMode)
  1223. m_nIDTracking = AFX_IDS_IDLEMESSAGE;
  1224. else
  1225. m_nIDTracking = AFX_IDS_HELPMODEMESSAGE;
  1226. SendMessage(WM_SETMESSAGESTRING, (WPARAM)m_nIDTracking);
  1227. ASSERT(m_nIDTracking == m_nIDLastMessage);
  1228. // update right away
  1229. CWnd* pWnd = GetMessageBar();
  1230. if (pWnd != NULL)
  1231. pWnd->UpdateWindow();
  1232. }
  1233. else
  1234. {
  1235. if (nItemID == 0 || nFlags & (MF_SEPARATOR|MF_POPUP))
  1236. {
  1237. // nothing should be displayed
  1238. m_nIDTracking = 0;
  1239. }
  1240. else if (nItemID >= 0xF000 && nItemID < 0xF1F0) // max of 31 SC_s
  1241. {
  1242. // special strings table entries for system commands
  1243. m_nIDTracking = ID_COMMAND_FROM_SC(nItemID);
  1244. ASSERT(m_nIDTracking >= AFX_IDS_SCFIRST &&
  1245. m_nIDTracking < AFX_IDS_SCFIRST + 31);
  1246. }
  1247. else if (nItemID >= AFX_IDM_FIRST_MDICHILD)
  1248. {
  1249. // all MDI Child windows map to the same help id
  1250. m_nIDTracking = AFX_IDS_MDICHILD;
  1251. }
  1252. else
  1253. {
  1254. // track on idle
  1255. m_nIDTracking = nItemID;
  1256. }
  1257. pFrameWnd->m_nFlags |= WF_NOPOPMSG;
  1258. }
  1259. // when running in-place, it is necessary to cause a message to
  1260. // be pumped through the queue.
  1261. if (m_nIDTracking != m_nIDLastMessage && GetParent() != NULL)
  1262. PostMessage(WM_KICKIDLE);
  1263. }
  1264. void CFrameWnd::GetMessageString(UINT nID, CString& rMessage) const
  1265. {
  1266. // load appropriate string
  1267. LPTSTR lpsz = rMessage.GetBuffer(255);
  1268. if (AfxLoadString(nID, lpsz) != 0)
  1269. {
  1270. // first newline terminates actual string
  1271. lpsz = _tcschr(lpsz, '\n');
  1272. if (lpsz != NULL)
  1273. *lpsz = '\0';
  1274. }
  1275. else
  1276. {
  1277. // not found
  1278. TRACE1("Warning: no message line prompt for ID 0x%04X.\n", nID);
  1279. }
  1280. rMessage.ReleaseBuffer();
  1281. }
  1282. LRESULT CFrameWnd::OnPopMessageString(WPARAM wParam, LPARAM lParam)
  1283. {
  1284. if (m_nFlags & WF_NOPOPMSG)
  1285. return 0;
  1286. return SendMessage(WM_SETMESSAGESTRING, wParam, lParam);
  1287. }
  1288. LRESULT CFrameWnd::OnSetMessageString(WPARAM wParam, LPARAM lParam)
  1289. {
  1290. UINT nIDLast = m_nIDLastMessage;
  1291. m_nFlags &= ~WF_NOPOPMSG;
  1292. CWnd* pMessageBar = GetMessageBar();
  1293. if (pMessageBar != NULL)
  1294. {
  1295. LPCTSTR lpsz = NULL;
  1296. CString strMessage;
  1297. // set the message bar text
  1298. if (lParam != 0)
  1299. {
  1300. ASSERT(wParam == 0); // can't have both an ID and a string
  1301. lpsz = (LPCTSTR)lParam; // set an explicit string
  1302. }
  1303. else if (wParam != 0)
  1304. {
  1305. // map SC_CLOSE to PREVIEW_CLOSE when in print preview mode
  1306. if (wParam == AFX_IDS_SCCLOSE && m_lpfnCloseProc != NULL)
  1307. wParam = AFX_IDS_PREVIEW_CLOSE;
  1308. // get message associated with the ID indicated by wParam
  1309. GetMessageString(wParam, strMessage);
  1310. lpsz = strMessage;
  1311. }
  1312. pMessageBar->SetWindowText(lpsz);
  1313. // update owner of the bar in terms of last message selected
  1314. CFrameWnd* pFrameWnd = pMessageBar->GetParentFrame();
  1315. if (pFrameWnd != NULL)
  1316. {
  1317. pFrameWnd->m_nIDLastMessage = (UINT)wParam;
  1318. pFrameWnd->m_nIDTracking = (UINT)wParam;
  1319. }
  1320. }
  1321. m_nIDLastMessage = (UINT)wParam; // new ID (or 0)
  1322. m_nIDTracking = (UINT)wParam; // so F1 on toolbar buttons work
  1323. return nIDLast;
  1324. }
  1325. LRESULT CFrameWnd::OnHelpPromptAddr(WPARAM, LPARAM)
  1326. {
  1327. return (LRESULT)&m_dwPromptContext;
  1328. }
  1329. CWnd* CFrameWnd::GetMessageBar()
  1330. {
  1331. return GetDescendantWindow(AFX_IDW_STATUS_BAR, TRUE);
  1332. }
  1333. void CFrameWnd::OnEnterIdle(UINT nWhy, CWnd* pWho)
  1334. {
  1335. CWnd::OnEnterIdle(nWhy, pWho);
  1336. if (nWhy != MSGF_MENU || m_nIDTracking == m_nIDLastMessage)
  1337. return;
  1338. SetMessageText(m_nIDTracking);
  1339. ASSERT(m_nIDTracking == m_nIDLastMessage);
  1340. }
  1341. void CFrameWnd::SetMessageText(LPCTSTR lpszText)
  1342. {
  1343. SendMessage(WM_SETMESSAGESTRING, 0, (LPARAM)lpszText);
  1344. }
  1345. void CFrameWnd::SetMessageText(UINT nID)
  1346. {
  1347. SendMessage(WM_SETMESSAGESTRING, (WPARAM)nID);
  1348. }
  1349. /////////////////////////////////////////////////////////////////////////////
  1350. // CFrameWnd standard control bar management
  1351. void CFrameWnd::DestroyDockBars()
  1352. {
  1353. // create a list of all the dock bars
  1354. // this is necessary because m_listControlBars will change
  1355. // as the dock bars and floating frames are destroyed
  1356. CPtrList listDockBars;
  1357. POSITION pos = m_listControlBars.GetHeadPosition();
  1358. while (pos != NULL)
  1359. {
  1360. CDockBar* pDockBar = (CDockBar*)m_listControlBars.GetNext(pos);
  1361. ASSERT(pDockBar != NULL);
  1362. if (pDockBar->IsDockBar())
  1363. listDockBars.AddTail(pDockBar);
  1364. }
  1365. pos = listDockBars.GetHeadPosition();
  1366. while (pos != NULL)
  1367. {
  1368. CDockBar* pDockBar = (CDockBar*)listDockBars.GetNext(pos);
  1369. if (pDockBar->m_bFloating)
  1370. {
  1371. CFrameWnd* pFrameWnd = pDockBar->GetParentFrame();
  1372. ASSERT_VALID(pFrameWnd);
  1373. pFrameWnd->DestroyWindow();
  1374. }
  1375. else
  1376. pDockBar->DestroyWindow();
  1377. }
  1378. }
  1379. CControlBar* CFrameWnd::GetControlBar(UINT nID)
  1380. {
  1381. if (nID == 0)
  1382. return NULL;
  1383. POSITION pos = m_listControlBars.GetHeadPosition();
  1384. while (pos != NULL)
  1385. {
  1386. CControlBar* pBar = (CControlBar*)m_listControlBars.GetNext(pos);
  1387. ASSERT(pBar != NULL);
  1388. if (_AfxGetDlgCtrlID(pBar->m_hWnd) == nID)
  1389. {
  1390. ASSERT_KINDOF(CControlBar, pBar);
  1391. return pBar;
  1392. }
  1393. }
  1394. return NULL;
  1395. }
  1396. void CFrameWnd::OnUpdateControlBarMenu(CCmdUI* pCmdUI)
  1397. {
  1398. ASSERT(ID_VIEW_STATUS_BAR == AFX_IDW_STATUS_BAR);
  1399. ASSERT(ID_VIEW_TOOLBAR == AFX_IDW_TOOLBAR);
  1400. ASSERT(ID_VIEW_REBAR == AFX_IDW_REBAR);
  1401. CControlBar* pBar = GetControlBar(pCmdUI->m_nID);
  1402. if (pBar != NULL)
  1403. {
  1404. pCmdUI->SetCheck((pBar->GetStyle() & WS_VISIBLE) != 0);
  1405. return;
  1406. }
  1407. pCmdUI->ContinueRouting();
  1408. }
  1409. BOOL CFrameWnd::OnBarCheck(UINT nID)
  1410. {
  1411. ASSERT(ID_VIEW_STATUS_BAR == AFX_IDW_STATUS_BAR);
  1412. ASSERT(ID_VIEW_TOOLBAR == AFX_IDW_TOOLBAR);
  1413. ASSERT(ID_VIEW_REBAR == AFX_IDW_REBAR);
  1414. CControlBar* pBar = GetControlBar(nID);
  1415. if (pBar != NULL)
  1416. {
  1417. ShowControlBar(pBar, (pBar->GetStyle() & WS_VISIBLE) == 0, FALSE);
  1418. return TRUE;
  1419. }
  1420. return FALSE;
  1421. }
  1422. BOOL CFrameWnd::OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult)
  1423. {
  1424. ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW);
  1425. // need to handle both ANSI and UNICODE versions of the message
  1426. TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
  1427. TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
  1428. TCHAR szFullText[256];
  1429. CString strTipText;
  1430. UINT nID = pNMHDR->idFrom;
  1431. if (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) ||
  1432. pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))
  1433. {
  1434. // idFrom is actually the HWND of the tool
  1435. nID = _AfxGetDlgCtrlID((HWND)nID);
  1436. }
  1437. if (nID != 0) // will be zero on a separator
  1438. {
  1439. // don't handle the message if no string resource found
  1440. if (AfxLoadString(nID, szFullText) == 0)
  1441. return FALSE;
  1442. // this is the command id, not the button index
  1443. AfxExtractSubString(strTipText, szFullText, 1, '\n');
  1444. }
  1445. #ifndef _UNICODE
  1446. if (pNMHDR->code == TTN_NEEDTEXTA)
  1447. lstrcpyn(pTTTA->szText, strTipText, _countof(pTTTA->szText));
  1448. else
  1449. _mbstowcsz(pTTTW->szText, strTipText, _countof(pTTTW->szText));
  1450. #else
  1451. if (pNMHDR->code == TTN_NEEDTEXTA)
  1452. _wcstombsz(pTTTA->szText, strTipText, _countof(pTTTA->szText));
  1453. else
  1454. lstrcpyn(pTTTW->szText, strTipText, _countof(pTTTW->szText));
  1455. #endif
  1456. *pResult = 0;
  1457. // bring the tooltip window above other popup windows
  1458. ::SetWindowPos(pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0,
  1459. SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER);
  1460. return TRUE; // message was handled
  1461. }
  1462. /////////////////////////////////////////////////////////////////////////////
  1463. // Support for standard status bar
  1464. void CFrameWnd::OnUpdateKeyIndicator(CCmdUI* pCmdUI)
  1465. {
  1466. UINT nVK;
  1467. UINT flag = 0x0001;
  1468. switch (pCmdUI->m_nID)
  1469. {
  1470. case ID_INDICATOR_CAPS:
  1471. nVK = VK_CAPITAL;
  1472. break;
  1473. case ID_INDICATOR_NUM:
  1474. nVK = VK_NUMLOCK;
  1475. break;
  1476. case ID_INDICATOR_SCRL:
  1477. nVK = VK_SCROLL;
  1478. break;
  1479. case ID_INDICATOR_KANA:
  1480. nVK = VK_KANA;
  1481. // WINBUG: Special case for Windows 3.x. The wrong bit was toggled
  1482. // in those systems so this must be special cased. This is fixed
  1483. // on systems whose version is 4.x or greater.
  1484. if (!afxData.bWin4)
  1485. flag = 0x8000;
  1486. break;
  1487. default:
  1488. TRACE1("Warning: OnUpdateKeyIndicator - unknown indicator 0x%04X.\n",
  1489. pCmdUI->m_nID);
  1490. pCmdUI->ContinueRouting();
  1491. return; // not for us
  1492. }
  1493. pCmdUI->Enable(::GetKeyState(nVK) & flag);
  1494. // enable static text based on toggled key state
  1495. ASSERT(pCmdUI->m_bEnableChanged);
  1496. }
  1497. void CFrameWnd::OnUpdateContextHelp(CCmdUI* pCmdUI)
  1498. {
  1499. if (AfxGetMainWnd() == this)
  1500. pCmdUI->SetCheck(!!m_bHelpMode);
  1501. else
  1502. pCmdUI->ContinueRouting();
  1503. }
  1504. /////////////////////////////////////////////////////////////////////////////
  1505. // Setting title of frame window - UISG standard
  1506. void CFrameWnd::OnUpdateFrameTitle(BOOL bAddToTitle)
  1507. {
  1508. if ((GetStyle() & FWS_ADDTOTITLE) == 0)
  1509. return; // leave it alone!
  1510. #ifndef _AFX_NO_OLE_SUPPORT
  1511. // allow hook to set the title (used for OLE support)
  1512. if (m_pNotifyHook != NULL && m_pNotifyHook->OnUpdateFrameTitle())
  1513. return;
  1514. #endif
  1515. CDocument* pDocument = GetActiveDocument();
  1516. if (bAddToTitle && pDocument != NULL)
  1517. UpdateFrameTitleForDocument(pDocument->GetTitle());
  1518. else
  1519. UpdateFrameTitleForDocument(NULL);
  1520. }
  1521. void CFrameWnd::UpdateFrameTitleForDocument(LPCTSTR lpszDocName)
  1522. {
  1523. // copy first part of title loaded at time of frame creation
  1524. TCHAR szText[256+_MAX_PATH];
  1525. if (GetStyle() & FWS_PREFIXTITLE)
  1526. {
  1527. szText[0] = '\0'; // start with nothing
  1528. // get name of currently active view
  1529. if (lpszDocName != NULL)
  1530. {
  1531. lstrcpy(szText, lpszDocName);
  1532. // add current window # if needed
  1533. if (m_nWindow > 0)
  1534. wsprintf(szText + lstrlen(szText), _T(":%d"), m_nWindow);
  1535. lstrcat(szText, _T(" - "));
  1536. }
  1537. lstrcat(szText, m_strTitle);
  1538. }
  1539. else
  1540. {
  1541. // get name of currently active view
  1542. lstrcpy(szText, m_strTitle);
  1543. if (lpszDocName != NULL)
  1544. {
  1545. lstrcat(szText, _T(" - "));
  1546. lstrcat(szText, lpszDocName);
  1547. // add current window # if needed
  1548. if (m_nWindow > 0)
  1549. wsprintf(szText + lstrlen(szText), _T(":%d"), m_nWindow);
  1550. }
  1551. }
  1552. // set title if changed, but don't remove completely
  1553. // Note: will be excessive for MDI Frame with maximized child
  1554. AfxSetWindowText(m_hWnd, szText);
  1555. }
  1556. /////////////////////////////////////////////////////////////////////////////
  1557. void CFrameWnd::OnSetPreviewMode(BOOL bPreview, CPrintPreviewState* pState)
  1558. {
  1559. // default implementation changes control bars, menu and main pane window
  1560. #ifndef _AFX_NO_OLE_SUPPORT
  1561. CFrameWnd* pActiveFrame = GetActiveFrame();
  1562. ASSERT_VALID(pActiveFrame);
  1563. if (bPreview && pActiveFrame->m_pNotifyHook != NULL)
  1564. pActiveFrame->m_pNotifyHook->OnDocActivate(FALSE);
  1565. #endif
  1566. // Set visibility of standard ControlBars (only the first 32)
  1567. DWORD dwOldStates = 0;
  1568. POSITION pos = m_listControlBars.GetHeadPosition();
  1569. while (pos != NULL)
  1570. {
  1571. CControlBar* pBar = (CControlBar*)m_listControlBars.GetNext(pos);
  1572. ASSERT_VALID(pBar);
  1573. UINT nID = _AfxGetDlgCtrlID(pBar->m_hWnd);
  1574. if (nID >= AFX_IDW_CONTROLBAR_FIRST && nID <= AFX_IDW_CONTROLBAR_FIRST+31)
  1575. {
  1576. DWORD dwMask = 1L << (nID - AFX_IDW_CONTROLBAR_FIRST);
  1577. if (pBar->IsVisible())
  1578. dwOldStates |= dwMask; // save if previously visible
  1579. if (!pBar->IsDockBar() || nID != AFX_IDW_DOCKBAR_FLOAT)
  1580. ShowControlBar(pBar, (pState->dwStates & dwMask), TRUE);
  1581. }
  1582. }
  1583. pState->dwStates = dwOldStates; // save for restore
  1584. if (bPreview)
  1585. {
  1586. // Entering Print Preview
  1587. ASSERT(m_lpfnCloseProc == NULL); // no chaining
  1588. m_lpfnCloseProc = pState->lpfnCloseProc;
  1589. // show any modeless dialogs, popup windows, float tools, etc
  1590. ShowOwnedWindows(FALSE);
  1591. // Hide the main pane
  1592. HWND hWnd = ::GetDlgItem(m_hWnd, pState->nIDMainPane);
  1593. ASSERT(hWnd != NULL); // must be one that we are hiding!
  1594. ::ShowWindow(hWnd, SW_HIDE);
  1595. // Get rid of the menu first (will resize the window)
  1596. pState->hMenu = ::GetMenu(m_hWnd);
  1597. if (pState->hMenu != NULL)
  1598. {
  1599. // Invalidate before SetMenu since we are going to replace
  1600. // the frame's client area anyway
  1601. Invalidate();
  1602. SetMenu(NULL);
  1603. m_nIdleFlags &= ~idleMenu; // avoid any idle menu processing
  1604. }
  1605. // Save the accelerator table and remove it.
  1606. pState->hAccelTable = m_hAccelTable;
  1607. m_hAccelTable = NULL;
  1608. LoadAccelTable(MAKEINTRESOURCE(AFX_IDR_PREVIEW_ACCEL));
  1609. // Make room for the PreviewView by changing AFX_IDW_PANE_FIRST's ID
  1610. // to AFX_IDW_PREVIEW_FIRST
  1611. if (pState->nIDMainPane != AFX_IDW_PANE_FIRST)
  1612. hWnd = ::GetDlgItem(m_hWnd, AFX_IDW_PANE_FIRST);
  1613. if (hWnd != NULL)
  1614. _AfxSetDlgCtrlID(hWnd, AFX_IDW_PANE_SAVE);
  1615. #ifdef _DEBUG
  1616. if ((::GetWindowLong(m_hWnd, GWL_STYLE) & (WS_HSCROLL|WS_VSCROLL)) != 0)
  1617. TRACE0("Warning: scroll bars in frame windows may cause unusual behaviour.\n");
  1618. #endif
  1619. }
  1620. else
  1621. {
  1622. // Leaving Preview
  1623. m_lpfnCloseProc = NULL;
  1624. // shift original AFX_IDW_PANE_FIRST back to its rightful ID
  1625. HWND hWnd = ::GetDlgItem(m_hWnd, AFX_IDW_PANE_SAVE);
  1626. if (hWnd != NULL)
  1627. {
  1628. HWND hWndTemp = ::GetDlgItem(m_hWnd, AFX_IDW_PANE_FIRST);
  1629. if (hWndTemp != NULL)
  1630. _AfxSetDlgCtrlID(hWndTemp, AFX_IDW_PANE_SAVE);
  1631. _AfxSetDlgCtrlID(hWnd, AFX_IDW_PANE_FIRST);
  1632. }
  1633. // put the menu back in place if it was removed before
  1634. if (pState->hMenu != NULL)
  1635. {
  1636. // Invalidate before SetMenu since we are going to replace
  1637. // the frame's client area anyway
  1638. Invalidate();
  1639. ::SetMenu(m_hWnd, pState->hMenu);
  1640. }
  1641. // recalc layout now, before showing the main pane
  1642. #ifndef _AFX_NO_OLE_SUPPORT
  1643. if (pActiveFrame->m_pNotifyHook != NULL)
  1644. pActiveFrame->m_pNotifyHook->OnDocActivate(TRUE);
  1645. #endif
  1646. RecalcLayout();
  1647. // now show main pane that was hidden
  1648. if (pState->nIDMainPane != AFX_IDW_PANE_FIRST)
  1649. hWnd = ::GetDlgItem(m_hWnd, pState->nIDMainPane);
  1650. ASSERT(hWnd != NULL);
  1651. ::ShowWindow(hWnd, SW_SHOW);
  1652. // Restore the Accelerator table
  1653. m_hAccelTable = pState->hAccelTable;
  1654. // show any modeless dialogs, popup windows, float tools, etc
  1655. ShowOwnedWindows(TRUE);
  1656. }
  1657. }
  1658. void CFrameWnd::DelayUpdateFrameMenu(HMENU hMenuAlt)
  1659. {
  1660. m_hMenuAlt = hMenuAlt;
  1661. m_nIdleFlags |= idleMenu;
  1662. }
  1663. void CFrameWnd::OnIdleUpdateCmdUI()
  1664. {
  1665. // update menu if necessary
  1666. if (m_nIdleFlags & idleMenu)
  1667. OnUpdateFrameMenu(m_hMenuAlt);
  1668. // update title if necessary
  1669. if (m_nIdleFlags & idleTitle)
  1670. OnUpdateFrameTitle(TRUE);
  1671. // recalc layout if necessary
  1672. if (m_nIdleFlags & idleLayout)
  1673. {
  1674. RecalcLayout(m_nIdleFlags & idleNotify);
  1675. UpdateWindow();
  1676. }
  1677. // set the current message string if necessary
  1678. if (m_nIDTracking != m_nIDLastMessage)
  1679. {
  1680. SetMessageText(m_nIDTracking);
  1681. ASSERT(m_nIDTracking == m_nIDLastMessage);
  1682. }
  1683. m_nIdleFlags = 0;
  1684. }
  1685. CFrameWnd* CFrameWnd::GetActiveFrame()
  1686. {
  1687. // by default, the active frame is the frame itself (MDI is different)
  1688. return this;
  1689. }
  1690. void CFrameWnd::RecalcLayout(BOOL bNotify)
  1691. {
  1692. if (m_bInRecalcLayout)
  1693. return;
  1694. m_bInRecalcLayout = TRUE;
  1695. // clear idle flags for recalc layout if called elsewhere
  1696. if (m_nIdleFlags & idleNotify)
  1697. bNotify = TRUE;
  1698. m_nIdleFlags &= ~(idleLayout|idleNotify);
  1699. #ifndef _AFX_NO_OLE_SUPPORT
  1700. // call the layout hook -- OLE support uses this hook
  1701. if (bNotify && m_pNotifyHook != NULL)
  1702. m_pNotifyHook->OnRecalcLayout();
  1703. #endif
  1704. // reposition all the child windows (regardless of ID)
  1705. if (GetStyle() & FWS_SNAPTOBARS)
  1706. {
  1707. CRect rect(0, 0, 32767, 32767);
  1708. RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery,
  1709. &rect, &rect, FALSE);
  1710. RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposExtra,
  1711. &m_rectBorder, &rect, TRUE);
  1712. CalcWindowRect(&rect);
  1713. SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(),
  1714. SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
  1715. }
  1716. else
  1717. RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposExtra, &m_rectBorder);
  1718. m_bInRecalcLayout = FALSE;
  1719. }
  1720. // CFrameWnd implementation of OLE border space negotiation
  1721. BOOL CFrameWnd::NegotiateBorderSpace(UINT nBorderCmd, LPRECT lpRectBorder)
  1722. {
  1723. CRect border, request;
  1724. switch (nBorderCmd)
  1725. {
  1726. case borderGet:
  1727. ASSERT(lpRectBorder != NULL);
  1728. RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery,
  1729. lpRectBorder);
  1730. break;
  1731. case borderRequest:
  1732. return TRUE;
  1733. case borderSet:
  1734. if (lpRectBorder == NULL)
  1735. {
  1736. if (!m_rectBorder.IsRectNull())
  1737. {
  1738. // releasing all border space -- recalc needed
  1739. m_rectBorder.SetRectEmpty();
  1740. return TRUE;
  1741. }
  1742. // original rect is empty & lpRectBorder is NULL, no recalc needed
  1743. return FALSE;
  1744. }
  1745. if (!::EqualRect(m_rectBorder, lpRectBorder))
  1746. {
  1747. // the rects are different -- recalc needed
  1748. m_rectBorder.CopyRect(lpRectBorder);
  1749. return TRUE;
  1750. }
  1751. return FALSE; // no recalc needed
  1752. default:
  1753. ASSERT(FALSE); // invalid CFrameWnd::BorderCmd
  1754. }
  1755. return TRUE;
  1756. }
  1757. void CFrameWnd::OnSize(UINT nType, int cx, int cy)
  1758. {
  1759. CWnd::OnSize(nType, cx, cy); // important for MDI Children
  1760. if (nType != SIZE_MINIMIZED)
  1761. RecalcLayout();
  1762. }
  1763. BOOL CFrameWnd::OnEraseBkgnd(CDC* pDC)
  1764. {
  1765. if (m_pViewActive != NULL)
  1766. return TRUE; // active view will erase/paint itself
  1767. // for view-less frame just use the default background fill
  1768. return CWnd::OnEraseBkgnd(pDC);
  1769. }
  1770. LRESULT CFrameWnd::OnRegisteredMouseWheel(WPARAM wParam, LPARAM lParam)
  1771. {
  1772. // convert from MSH_MOUSEWHEEL to WM_MOUSEWHEEL
  1773. WORD keyState = 0;
  1774. keyState |= (::GetKeyState(VK_CONTROL) < 0) ? MK_CONTROL : 0;
  1775. keyState |= (::GetKeyState(VK_SHIFT) < 0) ? MK_SHIFT : 0;
  1776. LRESULT lResult;
  1777. HWND hwFocus = ::GetFocus();
  1778. const HWND hwDesktop = ::GetDesktopWindow();
  1779. if (hwFocus == NULL)
  1780. lResult = SendMessage(WM_MOUSEWHEEL, (wParam << 16) | keyState, lParam);
  1781. else
  1782. {
  1783. do {
  1784. lResult = ::SendMessage(hwFocus, WM_MOUSEWHEEL,
  1785. (wParam << 16) | keyState, lParam);
  1786. hwFocus = ::GetParent(hwFocus);
  1787. }
  1788. while (lResult == 0 && hwFocus != NULL && hwFocus != hwDesktop);
  1789. }
  1790. return lResult;
  1791. }
  1792. void CFrameWnd::ActivateFrame(int nCmdShow)
  1793. // nCmdShow is the normal show mode this frame should be in
  1794. {
  1795. // translate default nCmdShow (-1)
  1796. if (nCmdShow == -1)
  1797. {
  1798. if (!IsWindowVisible())
  1799. nCmdShow = SW_SHOWNORMAL;
  1800. else if (IsIconic())
  1801. nCmdShow = SW_RESTORE;
  1802. }
  1803. // bring to top before showing
  1804. BringToTop(nCmdShow);
  1805. if (nCmdShow != -1)
  1806. {
  1807. // show the window as specified
  1808. ShowWindow(nCmdShow);
  1809. // and finally, bring to top after showing
  1810. BringToTop(nCmdShow);
  1811. }
  1812. }
  1813. void CFrameWnd::BringToTop(int nCmdShow)
  1814. {
  1815. // place the window on top except for certain nCmdShow
  1816. if (nCmdShow != SW_HIDE &&
  1817. nCmdShow != SW_MINIMIZE && nCmdShow != SW_SHOWMINNOACTIVE &&
  1818. nCmdShow != SW_SHOWNA && nCmdShow != SW_SHOWNOACTIVATE)
  1819. {
  1820. // if no last active popup, it will return m_hWnd
  1821. HWND hWndLastPop = ::GetLastActivePopup(m_hWnd);
  1822. ::BringWindowToTop(hWndLastPop);
  1823. }
  1824. }
  1825. /////////////////////////////////////////////////////////////////////////////
  1826. // CFrameWnd Diagnostics
  1827. #ifdef _DEBUG
  1828. void CFrameWnd::AssertValid() const
  1829. {
  1830. CWnd::AssertValid();
  1831. if (m_pViewActive != NULL)
  1832. ASSERT_VALID(m_pViewActive);
  1833. }
  1834. void CFrameWnd::Dump(CDumpContext& dc) const
  1835. {
  1836. CWnd::Dump(dc);
  1837. dc << "m_hAccelTable = " << (UINT)m_hAccelTable;
  1838. dc << "\nm_nWindow = " << m_nWindow;
  1839. dc << "\nm_nIDHelp = " << m_nIDHelp;
  1840. dc << "\nm_nIDTracking = " << m_nIDTracking;
  1841. dc << "\nm_nIDLastMessage = " << m_nIDLastMessage;
  1842. if (m_pViewActive != NULL)
  1843. dc << "\nwith active view: " << m_pViewActive;
  1844. else
  1845. dc << "\nno active view";
  1846. dc << "\n";
  1847. }
  1848. #endif //_DEBUG
  1849. /////////////////////////////////////////////////////////////////////////////
  1850. // CControlBar segmentation
  1851. CFrameWnd* CControlBar::GetDockingFrame() const
  1852. {
  1853. CFrameWnd* pFrameWnd = GetParentFrame();
  1854. if (pFrameWnd == NULL)
  1855. pFrameWnd = m_pDockSite;
  1856. ASSERT(pFrameWnd != NULL);
  1857. ASSERT_KINDOF(CFrameWnd, pFrameWnd);
  1858. return pFrameWnd;
  1859. }
  1860. BOOL CControlBar::IsFloating() const
  1861. {
  1862. if (IsDockBar())
  1863. return ((CDockBar*)this)->m_bFloating;
  1864. else
  1865. return m_pDockBar != NULL && m_pDockBar->m_bFloating;
  1866. }
  1867. #ifdef AFX_INIT_SEG
  1868. #pragma code_seg(AFX_INIT_SEG)
  1869. #endif
  1870. // in this file for IsKindOf library granularity (IsKindOf references these)
  1871. IMPLEMENT_DYNCREATE(CFrameWnd, CWnd)
  1872. IMPLEMENT_DYNAMIC(CView, CWnd)
  1873. IMPLEMENT_DYNAMIC(CControlBar, CWnd)
  1874. /////////////////////////////////////////////////////////////////////////////