Stroika Library 3.0d25
 
Loading...
Searching...
No Matches
MFC.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#include "Stroika/Foundation/Characters/LineEndings.h"
7
8namespace Stroika::Frameworks::Led::Platform {
9
10 /*
11 @METHOD: AsCPoint
12 @DESCRIPTION: Convert a @'Led_Point' to an MFC CPoint.
13 <p>See also @'AsLedPoint', @'AsCRect', @'AsLedRect'.
14 */
15 inline CPoint AsCPoint (Led_Point p)
16 {
17 return CPoint (p.h, p.v);
18 }
19 /*
20 @METHOD: AsLedPoint
21 @DESCRIPTION: Convert an MFC CPoint to a @'Led_Point'.
22 <p>See also @'AsCPoint', @'AsCRect', @'AsLedRect'.
23 */
24 inline Led_Point AsLedPoint (CPoint p)
25 {
26 return Led_Point (p.y, p.x);
27 }
28 /*
29 @METHOD: AsCRect
30 @DESCRIPTION: Convert a Led_Rect to an MFC CRect.
31 <p>See also @'AsCPoint', @'AsLedPoint', @'AsLedRect'.
32 */
33 inline CRect AsCRect (Led_Rect r)
34 {
35 return CRect (r.left, r.top, r.right, r.bottom);
36 }
37 /*
38 @METHOD: AsLedRect
39 @DESCRIPTION: Convert an MFC CRect to a Led_Rect.
40 <p>See also @'AsCPoint', @'AsLedPoint', @'AsCRect'.
41 */
42 inline Led_Rect AsLedRect (CRect r)
43 {
44 return Led_Rect (r.top, r.left, r.Height (), r.Width ());
45 }
46 /*
47 @METHOD: AsCSize
48 @DESCRIPTION: Convert a Led_Size to an MFC CSize.
49 */
50 inline CSize AsCSize (Led_Size s)
51 {
52 return CSize (s.h, s.v);
53 }
54
55 // class Led_MFC_CDCFromTablet
56 inline Led_MFC_CDCFromTablet::Led_MFC_CDCFromTablet (Tablet* t)
57 : fCDC ()
58 {
60 fCDC.m_hDC = t->m_hDC;
61 fCDC.m_hAttribDC = t->m_hAttribDC;
62 fCDC.m_bPrinting = t->m_bPrinting;
63 }
64 inline Led_MFC_CDCFromTablet::~Led_MFC_CDCFromTablet ()
65 {
66 fCDC.Detach ();
67 }
68 inline Led_MFC_CDCFromTablet::operator CDC*()
69 {
70 return &fCDC;
71 }
72
73 // class Led_MFC_TabletFromCDC
74 inline Led_MFC_TabletFromCDC::Led_MFC_TabletFromCDC (CDC* pDC)
75 : fTablet ()
76 {
77 RequireNotNull (pDC);
78 fTablet.m_hDC = pDC->m_hDC;
79 fTablet.m_hAttribDC = pDC->m_hAttribDC;
80 fTablet.m_bPrinting = pDC->m_bPrinting;
81 }
82 inline Led_MFC_TabletFromCDC::~Led_MFC_TabletFromCDC ()
83 {
84 fTablet.Detach ();
85 }
86 inline Led_MFC_TabletFromCDC::operator Tablet*()
87 {
88 return &fTablet;
89 }
90 inline Tablet* Led_MFC_TabletFromCDC::operator->()
91 {
92 return &fTablet;
93 }
94
95 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
96 inline Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::Led_MFC_Helper ()
97 : LED_WIN32_HELPER ()
98 , MFC_BASE_CLASS ()
99 {
100 }
101 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
102 inline Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::~Led_MFC_Helper ()
103 {
104 }
105 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
106 HWND Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::GetHWND () const
107 {
108 return this->m_hWnd;
109 }
110 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
111 int Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnCreate (LPCREATESTRUCT lpCreateStruct)
112 {
113 RequireNotNull (lpCreateStruct);
114 if (MFC_BASE_CLASS::OnCreate (lpCreateStruct) != 0) {
115 return -1; // failed to create
116 }
117 this->TabletChangedMetrics (); // maybe should catch failures here, and return -1?
118 if ((lpCreateStruct->style & WS_VSCROLL) and this->GetScrollBarType (TextInteractor::v) == TextInteractor::eScrollBarNever) {
119 this->SetScrollBarType (TextInteractor::v, TextInteractor::eScrollBarAlways);
120 }
121 if ((lpCreateStruct->style & WS_HSCROLL) and this->GetScrollBarType (TextInteractor::h) == TextInteractor::eScrollBarNever) {
122 this->SetScrollBarType (TextInteractor::h, TextInteractor::eScrollBarAlways);
123 }
124 return 0; // sucess
125 }
126 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
127 void Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnPaint ()
128 {
129 CPaintDC dc (this);
130 CRect boundsRect = CRect (0, 0, 0, 0);
131 Verify (dc.GetClipBox (&boundsRect) != ERROR);
132 this->WindowDrawHelper (Led_MFC_TabletFromCDC (&dc), AsLedRect (boundsRect), false);
133 }
134 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
135 /*
136 @METHOD: Led_MFC_Helper<MFC_BASE_CLASS,BASE_INTERACTOR>::OnSetCursor
137 @DESCRIPTION: Hook the Win32 SDK WM_SETCURSOR message to handle set the cursor to an I-Beam, as appropriate. When over
138 draggable text, instead use a standard arrow cursor.
139 */
140 BOOL Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnSetCursor (CWnd* pWnd, UINT nHitTest, UINT message)
141 {
142 return this->OnSetCursor_Msg (pWnd->GetSafeHwnd (), nHitTest, message);
143 }
144 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
145 UINT Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnGetDlgCode ()
146 {
147 return this->OnGetDlgCode_Msg ();
148 }
149 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
150 void Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnChar (UINT nChar, UINT nRepCnt, UINT nFlags)
151 {
152 this->OnChar_Msg (nChar, nRepCnt + (nFlags << 16));
153 }
154 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
155 void Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnKeyDown (UINT nChar, UINT nRepCnt, UINT nFlags)
156 {
157 this->OnKeyDown_Msg (nChar, nRepCnt + (nFlags << 16));
158 }
159 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
160 void Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnMouseMove (UINT nFlags, CPoint oPoint)
161 {
162 this->OnMouseMove_Msg (nFlags, oPoint.x, oPoint.y);
163 }
164 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
165 /*
166 @METHOD: Led_MFC_Helper<MFC_BASE_CLASS,BASE_INTERACTOR>::ReplaceWindow
167 @DESCRIPTION: <p>Similar to @'Led_Win32_SimpleWndProc_Helper<BASE_INTERACTOR>::ReplaceWindow'
168 except that it works with MFC windows and MFC's CWnd message maps etc.
169 </p>
170 */
171 BOOL Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::ReplaceWindow (HWND hWnd)
172 {
173 CWnd* parent = MFC_BASE_CLASS::FromHandle (hWnd)->GetParent ();
174 HWND hwndParent = parent->GetSafeHwnd ();
175 if (hwndParent == NULL) {
176 return false;
177 }
178
179 int id = ::GetWindowLong (hWnd, GWL_ID);
180
181 HWND hwndEdit = ::GetDlgItem (hwndParent, id);
182 AssertNotNull (hwndEdit);
183
184 DWORD dwStyle = ::GetWindowLong (hwndEdit, GWL_STYLE);
185 DWORD exStyle = ::GetWindowLong (hwndEdit, GWL_EXSTYLE);
186
187 // Assume edit widget's position.
188 WINDOWPLACEMENT wp;
189 memset (&wp, 0, sizeof (wp));
190 wp.length = sizeof (wp);
191 Verify (::GetWindowPlacement (hwndEdit, &wp));
192
193 // Delete the edit widget window.
194 ::DestroyWindow (hwndEdit);
195
196 return MFC_BASE_CLASS::CreateEx (exStyle, NULL, NULL, dwStyle | WS_CHILD, wp.rcNormalPosition.left, wp.rcNormalPosition.top,
197 wp.rcNormalPosition.right - wp.rcNormalPosition.left,
198 wp.rcNormalPosition.bottom - wp.rcNormalPosition.top, parent->GetSafeHwnd (), (HMENU)id, NULL);
199 }
200 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
201 /*
202 @METHOD: Led_MFC_Helper<MFC_BASE_CLASS,BASE_INTERACTOR>::GetWindowRect
203 @DESCRIPTION: Return the Led WindowRect. This name is a somewhat unfortunate choice for Windows, because WindowRect means something
204 vaguely similar, but substantially different in the Win32 SDK.
205 <p>In the future, I may need to consider changing this name. But for now, I can think of none better.
206 <p>I provide two overloads of this routine. The one that returns a Led_Rect returns the Led WindowRect. And the one
207 that takes an LPRECT parameter returns the Win32 SDK WindowRect.
208 */
209 inline Led_Rect Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::GetWindowRect () const
210 {
211 return TextImager::GetWindowRect ();
212 }
213 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
214 inline void Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::GetWindowRect (LPRECT lpRect) const
215 {
216 // The CWnd version of GetWindowRect ()
217 const CWnd* cwnd = this;
218 CWnd* wnd = const_cast<CWnd*> (cwnd);
219 wnd->GetWindowRect (lpRect);
220 }
221 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
222 inline DWORD Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::GetStyle () const
223 {
224 return MFC_BASE_CLASS::GetStyle ();
225 }
226 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
227 void Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnLButtonDown (UINT nFlags, CPoint oPoint)
228 {
229 this->OnLButtonDown_Msg (nFlags, oPoint.x, oPoint.y);
230 }
231 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
232 void Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnLButtonUp (UINT nFlags, CPoint oPoint)
233 {
234 this->OnLButtonUp_Msg (nFlags, oPoint.x, oPoint.y);
235 }
236 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
237 void Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnLButtonDblClk (UINT nFlags, CPoint oPoint)
238 {
239 this->OnLButtonDblClk_Msg (nFlags, oPoint.x, oPoint.y);
240 }
241 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
242 void Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnSetFocus (CWnd* pOldWnd)
243 {
244 MFC_BASE_CLASS::OnSetFocus (pOldWnd);
245 this->OnSetFocus_Msg (pOldWnd->GetSafeHwnd ());
246 }
247 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
248 void Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnKillFocus (CWnd* pNewWnd)
249 {
250 this->OnKillFocus_Msg (pNewWnd->GetSafeHwnd ());
251 MFC_BASE_CLASS::OnKillFocus (pNewWnd);
252 }
253 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
254 void Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnSize (UINT nType, int cx, int cy)
255 {
256 MFC_BASE_CLASS::OnSize (nType, cx, cy);
257 this->OnSize_Msg ();
258 }
259 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
260 BOOL Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnEraseBkgnd (CDC* pDC)
261 {
262 return this->OnEraseBkgnd_Msg (pDC->GetSafeHdc ());
263 }
264 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
265 void Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnVScroll (UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
266 {
267 this->OnVScroll_Msg (nSBCode, nPos, pScrollBar->GetSafeHwnd ());
268 }
269 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
270 void Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnHScroll (UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
271 {
272 this->OnHScroll_Msg (nSBCode, nPos, pScrollBar->GetSafeHwnd ());
273 }
274 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
275 BOOL Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnMouseWheel (UINT fFlags, short zDelta, CPoint point)
276 {
277 return this->OnMouseWheel_Msg (MAKEWPARAM (fFlags, zDelta), MAKELPARAM (point.x, point.y));
278 }
279 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
280 void Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnEnable (BOOL bEnable)
281 {
282 this->OnEnable_Msg (!!bEnable);
283 }
284 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
285 void Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnTimer (UINT_PTR nEventID)
286 {
287 this->OnTimer_Msg (nEventID, NULL);
288 }
289 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
290 inline LRESULT Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnUniChar ([[maybe_unused]] WPARAM wParam, [[maybe_unused]] LPARAM lParam)
291 {
292 return LED_WIN32_HELPER::OnUniChar_Msg (wParam, lParam);
293 }
294 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
295 inline LRESULT Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnIMEChar ([[maybe_unused]] WPARAM wParam, [[maybe_unused]] LPARAM lParam)
296 {
297 return MFC_BASE_CLASS::Default ();
298 }
299 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
300 inline LRESULT Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnIME_COMPOSITION ([[maybe_unused]] WPARAM wParam, [[maybe_unused]] LPARAM lParam)
301 {
302 return MFC_BASE_CLASS::Default ();
303 }
304 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
305 inline LRESULT Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnIME_ENDCOMPOSITION ([[maybe_unused]] WPARAM wParam, [[maybe_unused]] LPARAM lParam)
306 {
307 return MFC_BASE_CLASS::Default ();
308 }
309 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
310 void Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnUpdateCommand_MSG (CCmdUI* pCmdUI)
311 {
312 RequireNotNull (pCmdUI);
313 if (not this->OnUpdateCommand (Led_MFC_TmpCmdUpdater (pCmdUI))) {
314 pCmdUI->Enable (false); // disable commands by default (SPR#1462)
315 }
316 }
317 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
318 void Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::OnPerformCommand_MSG (UINT commandNumber)
319 {
320 using namespace Stroika::Foundation;
322 IdleManager::NonIdleContext nonIdleContext;
323 try {
324 (void)this->OnPerformCommand (MFC_CommandNumberMapping::Get ().Lookup (commandNumber));
325 }
326 catch (...) {
327 DbgTrace ("Ignoring / suppressing uncaught exception in PerformCommand: {}"_f, current_exception ());
328 }
329 }
330 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
331 const AFX_MSGMAP* Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::GetMessageMap () const
332 {
333 return this->GetThisMessageMap ();
334 }
335 template <typename MFC_BASE_CLASS, typename BASE_INTERACTOR>
336 const AFX_MSGMAP* PASCAL Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>::GetThisMessageMap ()
337 {
338 using ThisClass = Led_MFC_Helper<MFC_BASE_CLASS, BASE_INTERACTOR>;
339 using TheBaseClass = MFC_BASE_CLASS;
340 DISABLE_COMPILER_MSC_WARNING_START (4407) // Not sure this is safe to ignore but I think it is due to qStroika_Frameworks_Led_MFCRequiresCWndLeftmostBaseClass
341 static const AFX_MSGMAP_ENTRY _messageEntries[] = {
342 ON_WM_CREATE () ON_WM_CHAR () ON_WM_TIMER () ON_WM_KEYDOWN () ON_WM_PAINT () ON_WM_MOUSEMOVE () ON_WM_LBUTTONDOWN ()
343 ON_WM_SETCURSOR () ON_WM_GETDLGCODE () ON_WM_LBUTTONUP () ON_WM_LBUTTONDBLCLK () ON_WM_SETFOCUS () ON_WM_KILLFOCUS ()
344 ON_WM_SIZE () ON_WM_ERASEBKGND () ON_WM_VSCROLL () ON_WM_HSCROLL () ON_WM_MOUSEWHEEL () ON_WM_ENABLE () ON_MESSAGE (
345 WM_UNICHAR, &OnUniChar) ON_MESSAGE (WM_IME_CHAR, &OnIMEChar) ON_MESSAGE (WM_IME_COMPOSITION, &OnIME_COMPOSITION)
346 ON_MESSAGE (WM_IME_ENDCOMPOSITION, &OnIME_ENDCOMPOSITION) LED_MFC_HANDLE_COMMAND_M (BASE_INTERACTOR::kUndo_CmdID)
347 LED_MFC_HANDLE_COMMAND_M (BASE_INTERACTOR::kRedo_CmdID) LED_MFC_HANDLE_COMMAND_M (BASE_INTERACTOR::kSelectAll_CmdID)
348 LED_MFC_HANDLE_COMMAND_M (BASE_INTERACTOR::kSelectWord_CmdID) LED_MFC_HANDLE_COMMAND_M (
349 BASE_INTERACTOR::kSelectTextRow_CmdID) LED_MFC_HANDLE_COMMAND_M (BASE_INTERACTOR::kSelectParagraph_CmdID)
350 LED_MFC_HANDLE_COMMAND_M (BASE_INTERACTOR::kCut_CmdID) LED_MFC_HANDLE_COMMAND_M (BASE_INTERACTOR::kCopy_CmdID)
351 LED_MFC_HANDLE_COMMAND_M (BASE_INTERACTOR::kPaste_CmdID) LED_MFC_HANDLE_COMMAND_M (BASE_INTERACTOR::kClear_CmdID)
352 LED_MFC_HANDLE_COMMAND_M (BASE_INTERACTOR::kFind_CmdID) LED_MFC_HANDLE_COMMAND_M (BASE_INTERACTOR::kFindAgain_CmdID)
353 LED_MFC_HANDLE_COMMAND_M (BASE_INTERACTOR::kEnterFindString_CmdID)
354 LED_MFC_HANDLE_COMMAND_M (BASE_INTERACTOR::kReplace_CmdID)
355 LED_MFC_HANDLE_COMMAND_M (BASE_INTERACTOR::kReplaceAgain_CmdID) LED_MFC_HANDLE_COMMAND_M (
356 BASE_INTERACTOR::kSpellCheck_CmdID){0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0}};
357 DISABLE_COMPILER_MSC_WARNING_END (4407)
358 static const AFX_MSGMAP messageMap = {&TheBaseClass::GetThisMessageMap, &_messageEntries[0]};
359 return &messageMap;
360 }
361
362 // class Led_MFC_MimicMFCAPIHelper<BASECLASS>
363 template <typename BASECLASS>
364 inline BOOL Led_MFC_MimicMFCAPIHelper<BASECLASS>::Create (DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
365 {
366 return BASECLASS::Create (NULL, NULL, dwStyle, rect, pParentWnd, nID);
367 }
368 template <typename BASECLASS>
369 inline BOOL Led_MFC_MimicMFCAPIHelper<BASECLASS>::CanUndo () const
370 {
371 Assert (::IsWindow (this->m_hWnd));
372 return (BOOL)::SendMessage (this->m_hWnd, EM_CANUNDO, 0, 0);
373 }
374 template <typename BASECLASS>
375 inline int Led_MFC_MimicMFCAPIHelper<BASECLASS>::GetLineCount_CEdit () const
376 {
377 Assert (::IsWindow (this->m_hWnd));
378 return (int)::SendMessage (this->m_hWnd, EM_GETLINECOUNT, 0, 0);
379 }
380 template <typename BASECLASS>
381 inline BOOL Led_MFC_MimicMFCAPIHelper<BASECLASS>::GetModify () const
382 {
383 Assert (false); // though THIS code is fine - we haven't yet hooked the callback, so this call will
384 // produce poor results... LGP 941129
385 Assert (::IsWindow (this->m_hWnd));
386 return (BOOL)::SendMessage (this->m_hWnd, EM_GETMODIFY, 0, 0);
387 }
388 template <typename BASECLASS>
389 inline void Led_MFC_MimicMFCAPIHelper<BASECLASS>::SetModify (BOOL bModified)
390 {
391 Assert (false); // though THIS code is fine - we haven't yet hooked the callback, so this call will
392 // produce poor results... LGP 941129
393 Assert (::IsWindow (this->m_hWnd));
394 ::SendMessage (this->m_hWnd, EM_SETMODIFY, bModified, 0);
395 }
396 template <typename BASECLASS>
397 inline void Led_MFC_MimicMFCAPIHelper<BASECLASS>::GetRect (LPRECT lpRect) const
398 {
399 Assert (false); // though THIS code is fine - we haven't yet hooked the callback, so this call will
400 // produce poor results... LGP 941129
401 Assert (::IsWindow (this->m_hWnd));
402 ::SendMessage (this->m_hWnd, EM_GETRECT, 0, (LPARAM)lpRect);
403 }
404 template <typename BASECLASS>
405 inline void Led_MFC_MimicMFCAPIHelper<BASECLASS>::GetSel (int& nStartChar, int& nEndChar) const
406 {
407 Assert (::IsWindow (this->m_hWnd));
408 ::SendMessage (this->m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar);
409 }
410 template <typename BASECLASS>
411 inline DWORD Led_MFC_MimicMFCAPIHelper<BASECLASS>::GetSel () const
412 {
413 Assert (::IsWindow (this->m_hWnd));
414 return ::SendMessage (this->m_hWnd, EM_GETSEL, 0, 0);
415 }
416 template <typename BASECLASS>
417 inline int Led_MFC_MimicMFCAPIHelper<BASECLASS>::GetLine (int nIndex, LPTSTR lpszBuffer) const
418 {
419 Assert (false); // though THIS code is fine - we haven't yet hooked the callback, so this call will
420 // produce poor results... LGP 941129
421 Assert (::IsWindow (this->m_hWnd));
422 return (int)::SendMessage (this->m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
423 }
424 template <typename BASECLASS>
425 inline int Led_MFC_MimicMFCAPIHelper<BASECLASS>::GetLine (int nIndex, LPTSTR lpszBuffer, int nMaxLength) const
426 {
427 Assert (false); // though THIS code is fine - we haven't yet hooked the callback, so this call will
428 // produce poor results... LGP 941129
429 Assert (::IsWindow (this->m_hWnd));
430 *(LPWORD)lpszBuffer = (WORD)nMaxLength;
431 return (int)::SendMessage (this->m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
432 }
433 template <typename BASECLASS>
434 inline void Led_MFC_MimicMFCAPIHelper<BASECLASS>::EmptyUndoBuffer ()
435 {
436 Assert (::IsWindow (this->m_hWnd));
437 ::SendMessage (this->m_hWnd, EM_EMPTYUNDOBUFFER, 0, 0);
438 }
439 template <typename BASECLASS>
440 inline BOOL Led_MFC_MimicMFCAPIHelper<BASECLASS>::FmtLines (BOOL bAddEOL)
441 {
442 Assert (false); // though THIS code is fine - we haven't yet hooked the callback, so this call will
443 // produce poor results... LGP 941129
444 Assert (::IsWindow (this->m_hWnd));
445 return (BOOL)::SendMessage (this->m_hWnd, EM_FMTLINES, bAddEOL, 0);
446 }
447 template <typename BASECLASS>
448 inline void Led_MFC_MimicMFCAPIHelper<BASECLASS>::LimitText (int nChars)
449 {
450 Assert (false); // though THIS code is fine - we haven't yet hooked the callback, so this call will
451 // produce poor results... LGP 941129
452 Assert (::IsWindow (this->m_hWnd));
453 ::SendMessage (this->m_hWnd, EM_LIMITTEXT, nChars, 0);
454 }
455 template <typename BASECLASS>
456 inline int Led_MFC_MimicMFCAPIHelper<BASECLASS>::LineFromChar (int nIndex) const
457 {
458 Assert (::IsWindow (this->m_hWnd));
459 return (int)::SendMessage (this->m_hWnd, EM_LINEFROMCHAR, nIndex, 0);
460 }
461 template <typename BASECLASS>
462 inline int Led_MFC_MimicMFCAPIHelper<BASECLASS>::LineIndex (int nLine) const
463 {
464 Assert (::IsWindow (this->m_hWnd));
465 return (int)::SendMessage (this->m_hWnd, EM_LINEINDEX, nLine, 0);
466 }
467 template <typename BASECLASS>
468 inline int Led_MFC_MimicMFCAPIHelper<BASECLASS>::LineLength (int nLine) const
469 {
470 Assert (::IsWindow (this->m_hWnd));
471 return (int)::SendMessage (this->m_hWnd, EM_LINELENGTH, nLine, 0);
472 }
473 template <typename BASECLASS>
474 inline void Led_MFC_MimicMFCAPIHelper<BASECLASS>::LineScroll (int nLines, int nChars)
475 {
476 Assert (::IsWindow (this->m_hWnd));
477 ::SendMessage (this->m_hWnd, EM_LINESCROLL, nChars, nLines);
478 }
479 template <typename BASECLASS>
480 inline void Led_MFC_MimicMFCAPIHelper<BASECLASS>::ReplaceSel (LPCTSTR lpszNewText)
481 {
482 AssertNotNull (lpszNewText);
483 Assert (::IsWindow (this->m_hWnd));
484 ::SendMessage (this->m_hWnd, EM_REPLACESEL, 0, (LPARAM)lpszNewText);
485 }
486 template <typename BASECLASS>
487 inline void Led_MFC_MimicMFCAPIHelper<BASECLASS>::SetPasswordChar (TCHAR ch)
488 {
489 Assert (false); // though THIS code is fine - we haven't yet hooked the callback, so this call will
490 // produce poor results... LGP 941129
491 Assert (::IsWindow (this->m_hWnd));
492 ::SendMessage (this->m_hWnd, EM_SETPASSWORDCHAR, ch, 0);
493 }
494 template <typename BASECLASS>
495 inline void Led_MFC_MimicMFCAPIHelper<BASECLASS>::SetRect (LPCRECT lpRect)
496 {
497 Assert (false); // though THIS code is fine - we haven't yet hooked the callback, so this call will
498 // produce poor results... LGP 941129
499 Assert (::IsWindow (this->m_hWnd));
500 ::SendMessage (this->m_hWnd, EM_SETRECT, 0, (LPARAM)lpRect);
501 }
502 template <typename BASECLASS>
503 inline void Led_MFC_MimicMFCAPIHelper<BASECLASS>::SetRectNP (LPCRECT lpRect)
504 {
505 Assert (false); // though THIS code is fine - we haven't yet hooked the callback, so this call will
506 // produce poor results... LGP 941129
507 Assert (::IsWindow (this->m_hWnd));
508 ::SendMessage (this->m_hWnd, EM_SETRECTNP, 0, (LPARAM)lpRect);
509 }
510 template <typename BASECLASS>
511 inline void Led_MFC_MimicMFCAPIHelper<BASECLASS>::SetSel (DWORD dwSelection, BOOL bNoScroll)
512 {
513 Assert (::IsWindow (this->m_hWnd));
514 ::SendMessage (this->m_hWnd, EM_SETSEL, LOWORD (dwSelection), HIWORD (dwSelection));
515 if (not bNoScroll) {
516 ::SendMessage (this->m_hWnd, EM_SCROLLCARET, 0, 0);
517 }
518 }
519 template <typename BASECLASS>
520 inline void Led_MFC_MimicMFCAPIHelper<BASECLASS>::SetSel (int nStartChar, int nEndChar, BOOL bNoScroll)
521 {
522 Assert (::IsWindow (this->m_hWnd));
523 ::SendMessage (this->m_hWnd, EM_SETSEL, nStartChar, nEndChar);
524 if (not bNoScroll) {
525 ::SendMessage (this->m_hWnd, EM_SCROLLCARET, 0, 0);
526 }
527 }
528 template <typename BASECLASS>
529 inline BOOL Led_MFC_MimicMFCAPIHelper<BASECLASS>::SetTabStops (int nTabStops, LPINT rgTabStops)
530 {
531 Assert (false); // though THIS code is fine - we haven't yet hooked the callback, so this call will
532 // produce poor results... LGP 941129
533 Assert (::IsWindow (this->m_hWnd));
534 return (BOOL)::SendMessage (this->m_hWnd, EM_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops);
535 }
536 template <typename BASECLASS>
537 inline void Led_MFC_MimicMFCAPIHelper<BASECLASS>::SetTabStops ()
538 {
539 Assert (false); // though THIS code is fine - we haven't yet hooked the callback, so this call will
540 // produce poor results... LGP 941129
541 Assert (::IsWindow (this->m_hWnd));
542 Verify (::SendMessage (this->m_hWnd, EM_SETTABSTOPS, 0, 0));
543 }
544 template <typename BASECLASS>
545 inline BOOL Led_MFC_MimicMFCAPIHelper<BASECLASS>::SetTabStops (const int& cxEachStop)
546 {
547 Assert (false); // though THIS code is fine - we haven't yet hooked the callback, so this call will
548 // produce poor results... LGP 941129
549 Assert (::IsWindow (this->m_hWnd));
550 return (BOOL)::SendMessage (this->m_hWnd, EM_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop);
551 }
552 template <typename BASECLASS>
553 inline BOOL Led_MFC_MimicMFCAPIHelper<BASECLASS>::Undo ()
554 {
555 Assert (::IsWindow (this->m_hWnd));
556 return (BOOL)::SendMessage (this->m_hWnd, EM_UNDO, 0, 0);
557 }
558 template <typename BASECLASS>
559 inline void Led_MFC_MimicMFCAPIHelper<BASECLASS>::Clear ()
560 {
561 Assert (::IsWindow (this->m_hWnd));
562 ::SendMessage (this->m_hWnd, WM_CLEAR, 0, 0);
563 }
564 template <typename BASECLASS>
565 inline void Led_MFC_MimicMFCAPIHelper<BASECLASS>::Copy ()
566 {
567 Assert (::IsWindow (this->m_hWnd));
568 ::SendMessage (this->m_hWnd, WM_COPY, 0, 0);
569 }
570 template <typename BASECLASS>
571 inline void Led_MFC_MimicMFCAPIHelper<BASECLASS>::Cut ()
572 {
573 Assert (::IsWindow (this->m_hWnd));
574 ::SendMessage (this->m_hWnd, WM_CUT, 0, 0);
575 }
576 template <typename BASECLASS>
577 inline void Led_MFC_MimicMFCAPIHelper<BASECLASS>::Paste ()
578 {
579 Assert (::IsWindow (this->m_hWnd));
580 ::SendMessage (this->m_hWnd, WM_PASTE, 0, 0);
581 }
582 template <typename BASECLASS>
583 inline BOOL Led_MFC_MimicMFCAPIHelper<BASECLASS>::SetReadOnly (BOOL bReadOnly)
584 {
585 Assert (::IsWindow (this->m_hWnd));
586 return (BOOL)::SendMessage (this->m_hWnd, EM_SETREADONLY, bReadOnly, 0L);
587 }
588 template <typename BASECLASS>
589 inline int Led_MFC_MimicMFCAPIHelper<BASECLASS>::GetFirstVisibleLine () const
590 {
591 Assert (::IsWindow (this->m_hWnd));
592 return (int)::SendMessage (this->m_hWnd, EM_GETFIRSTVISIBLELINE, 0, 0L);
593 }
594 template <typename BASECLASS>
595 inline TCHAR Led_MFC_MimicMFCAPIHelper<BASECLASS>::GetPasswordChar () const
596 {
597 Assert (false); // though THIS code is fine - we haven't yet hooked the callback, so this call will
598 // produce poor results... LGP 941129
599 Assert (::IsWindow (this->m_hWnd));
600 return (TCHAR)::SendMessage (this->m_hWnd, EM_GETPASSWORDCHAR, 0, 0L);
601 }
602
603 // class Led_MFC_OptionalWin32SDKMessageMimicHelper<BASECLASS>
604 template <typename BASECLASS>
605 const AFX_MSGMAP* Led_MFC_OptionalWin32SDKMessageMimicHelper<BASECLASS>::GetMessageMap () const
606 {
607 return GetThisMessageMap ();
608 }
609 template <typename BASECLASS>
610 const AFX_MSGMAP* PASCAL Led_MFC_OptionalWin32SDKMessageMimicHelper<BASECLASS>::GetThisMessageMap ()
611 {
612 using ThisClass = Led_MFC_OptionalWin32SDKMessageMimicHelper<BASECLASS>;
613 using TheBaseClass = BASECLASS;
614 DISABLE_COMPILER_MSC_WARNING_START (4407) // Not sure this is safe to ignore but I think it is due to qStroika_Frameworks_Led_MFCRequiresCWndLeftmostBaseClass
615 static const AFX_MSGMAP_ENTRY _messageEntries[] = {
616 ON_MESSAGE (WM_SETTEXT, &OnMFCSDKMessageDispatcher<WM_SETTEXT>) ON_MESSAGE (WM_GETTEXT, &OnMFCSDKMessageDispatcher<WM_GETTEXT>)
617 ON_MESSAGE (WM_GETTEXTLENGTH, &OnMFCSDKMessageDispatcher<WM_GETTEXTLENGTH>) ON_MESSAGE (
618 EM_GETSEL, &OnMFCSDKMessageDispatcher<EM_GETSEL>) ON_MESSAGE (EM_SETREADONLY, &OnMFCSDKMessageDispatcher<EM_SETREADONLY>)
619 ON_MESSAGE (EM_GETFIRSTVISIBLELINE, &OnMFCSDKMessageDispatcher<EM_GETFIRSTVISIBLELINE>) ON_MESSAGE (
620 EM_LINEINDEX, &OnMFCSDKMessageDispatcher<EM_LINEINDEX>) ON_MESSAGE (EM_GETLINECOUNT, &OnMFCSDKMessageDispatcher<EM_GETLINECOUNT>)
621 ON_MESSAGE (EM_CANUNDO, &OnMFCSDKMessageDispatcher<EM_CANUNDO>) ON_MESSAGE (EM_UNDO, &OnMFCSDKMessageDispatcher<EM_UNDO>)
622 ON_MESSAGE (EM_EMPTYUNDOBUFFER, &OnMFCSDKMessageDispatcher<EM_EMPTYUNDOBUFFER>)
623 ON_MESSAGE (WM_CLEAR, &OnMFCSDKMessageDispatcher<WM_CLEAR>) ON_MESSAGE (WM_CUT, &OnMFCSDKMessageDispatcher<WM_CUT>)
624 ON_MESSAGE (WM_COPY, &OnMFCSDKMessageDispatcher<WM_COPY>) ON_MESSAGE (WM_PASTE, &OnMFCSDKMessageDispatcher<WM_PASTE>)
625 ON_MESSAGE (EM_LINEFROMCHAR, &OnMFCSDKMessageDispatcher<EM_LINEFROMCHAR>)
626 ON_MESSAGE (EM_LINELENGTH, &OnMFCSDKMessageDispatcher<EM_LINELENGTH>)
627 ON_MESSAGE (EM_LINESCROLL, &OnMFCSDKMessageDispatcher<EM_LINESCROLL>)
628 ON_MESSAGE (EM_REPLACESEL, &OnMFCSDKMessageDispatcher<EM_REPLACESEL>)
629 ON_MESSAGE (EM_SETSEL, &OnMFCSDKMessageDispatcher<EM_SETSEL>)
630 ON_MESSAGE (EM_SCROLLCARET, &OnMFCSDKMessageDispatcher<EM_SCROLLCARET>)
631 ON_MESSAGE (WM_GETFONT, &OnMFCSDKMessageDispatcher<WM_GETFONT>)
632 ON_MESSAGE (WM_SETFONT, &OnMFCSDKMessageDispatcher<WM_SETFONT>){
633 0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0}};
634 DISABLE_COMPILER_MSC_WARNING_END (4407)
635 static const AFX_MSGMAP messageMap = {&TheBaseClass::GetThisMessageMap, &_messageEntries[0]};
636 return &messageMap;
637 }
638
639 // class Led_MFC_DragAndDropWindow<BASECLASS>
640 template <typename BASECLASS>
641 typename Led_MFC_DragAndDropWindow<BASECLASS>::LedStartDragAndDropContext* Led_MFC_DragAndDropWindow<BASECLASS>::sCurrentDragInfo = NULL;
642 template <typename BASECLASS>
643 Led_MFC_DragAndDropWindow<BASECLASS>::Led_MFC_DragAndDropWindow ()
644 : inherited ()
645 , fDropTarget ()
646 , fDragPoint ()
647 , fDragSize ()
648 , fDragOffset ()
649 , fPrevDropEffect (DROPEFFECT_NONE)
650 , fDragAutoScrollTimerID (0)
651 {
652 }
653 template <typename BASECLASS>
654 Led_MFC_DragAndDropWindow<BASECLASS>::~Led_MFC_DragAndDropWindow ()
655 {
656 Assert (fDragAutoScrollTimerID == 0);
657 }
658 template <typename BASECLASS>
659 /*
660 @METHOD: Led_MFC_DragAndDropWindow<BASECLASS>::GetCommandNames
661 @DESCRIPTION: Returns command name for each of the user-visible commands produced by this module.
662 This name is used used in the constructed Undo command name, as
663 in, "Undo Drag and Drop". You can replace this name with whatever you like.You change this value with
664 WordProcessor::SetCommandNames.
665 <p> The point of this is to allow for different UI-language localizations,
666 without having to change Led itself.
667 <p>See also @'Led_MFC_DragAndDropWindow<BASECLASS>::CommandNames'.
668 */
669 inline const Led_MFC_DragAndDropWindow<BASECLASS>::CommandNames& Led_MFC_DragAndDropWindow<BASECLASS>::GetCommandNames ()
670 {
671 return sCommandNames;
672 }
673 template <typename BASECLASS>
674 /*
675 @METHOD: Led_MFC_DragAndDropWindow<BASECLASS>::SetCommandNames
676 @DESCRIPTION: See @'Led_MFC_DragAndDropWindow<BASECLASS>::GetCommandNames'.
677 */
678 inline void Led_MFC_DragAndDropWindow<BASECLASS>::SetCommandNames (const typename Led_MFC_DragAndDropWindow<BASECLASS>::CommandNames& cmdNames)
679 {
680 sCommandNames = cmdNames;
681 }
682 template <typename BASECLASS>
683 typename Led_MFC_DragAndDropWindow<BASECLASS>::CommandNames Led_MFC_DragAndDropWindow<BASECLASS>::sCommandNames;
684 template <typename BASECLASS>
685 int Led_MFC_DragAndDropWindow<BASECLASS>::OnCreate (LPCREATESTRUCT lpCreateStruct)
686 {
687 if (inherited::OnCreate (lpCreateStruct) != 0) {
688 return -1; // failed to create
689 }
690 if (not fDropTarget.Register (this)) {
691 /*
692 * This can happen if the document associated with the view is not a COleDocument, for
693 * example. Shouldn't prevent Led view from being used. D&D just won't work...
694 */
695 TRACE (_T ("Warning: failed to register window as drop target\n"));
696 return 0; // treat this as OK - but warn above...
697 }
698 return 0; // success
699 }
700 template <typename BASECLASS>
701 bool Led_MFC_DragAndDropWindow<BASECLASS>::IsADragSelect (Led_Point clickedWhere) const
702 {
703 /*
704 * This seems to be what most people do. But I think this algorithm should
705 * be embellished, so we detect that the mouse is down for a while (a half second?)
706 * and then melt the drag into a regular selection. Also, pay attention to keys
707 * pressed etc as a hint of intent. But immediately return yes if we are moving
708 * what we've selected.
709 *
710 * For now though, just do it the simple way...
711 */
712 Region r;
713 this->GetSelectionWindowRegion (&r, this->GetSelectionStart (), this->GetSelectionEnd ());
714 return !!r.PtInRegion (AsCPoint (clickedWhere));
715 }
716 template <typename BASECLASS>
717 void Led_MFC_DragAndDropWindow<BASECLASS>::HandleDragSelect (UINT /*nFlags*/, CPoint oPoint)
718 {
719 const Foundation::Time::DurationSeconds kTimeEnoughToRestoreSelection = 0.3s;
720
721 using TextInteractor::eDefaultUpdate;
722
723 if (this->GetStyle () & WS_DISABLED) {
724 return;
725 }
726 if (this->GetFocus () != this) {
727 this->SetFocus ();
728 }
729
730 /*
731 * Be sure to reset these so on a double click after what looked like a single
732 * click we don't grab the old anchor (see spr#0438).
733 */
734 this->fMouseTrackingLastPoint = AsLedPoint (oPoint);
735 this->fDragAnchor = this->GetCharAtClickLocation (this->fMouseTrackingLastPoint);
736
737 Assert (sCurrentDragInfo == NULL);
738 sCurrentDragInfo = new LedStartDragAndDropContext{this};
739
740 sCurrentDragInfo->fOurDragStart = this->GetSelectionStart ();
741 sCurrentDragInfo->fOurDragEnd = this->GetSelectionEnd ();
742
743 try {
744 COleDataSource dataSrc;
745 Led_MFCWriterDAndDFlavorPackage flavorPackage (&dataSrc);
746 this->ExternalizeFlavors (flavorPackage);
747
748 Region selectionRegion;
749 this->GetSelectionWindowRegion (&selectionRegion, this->GetSelectionStart (), this->GetSelectionEnd ());
750
751 Foundation::Time::TimePointSeconds startDragSelectAt = Foundation::Time::GetTickCount (); // Grab it after the ExternalizeFlavors call in case thats slow (SPR#1498).
752 ::DROPEFFECT dropResult = DROPEFFECT_COPY;
753 if (not(this->GetStyle () & ES_READONLY)) {
754 // Assure we don't change read-only text.
755 dropResult |= DROPEFFECT_MOVE;
756 }
757 dropResult = dataSrc.DoDragDrop (dropResult);
759 if (this->GetStyle () & ES_READONLY) {
760 Assert (not(dropResult & DROPEFFECT_MOVE));
761 }
762 }
763 switch (dropResult) {
764 case DROPEFFECT_NONE: {
765 AssertNotNull (sCurrentDragInfo);
766 if (Foundation::Time::GetTickCount () - startDragSelectAt > kTimeEnoughToRestoreSelection) {
767 /*
768 * SPR#1374 - on aborted drag - restore the selection to its original value, rather
769 * than setting it to an empty selection where the user had clicked.
770 */
771 this->SetSelection (sCurrentDragInfo->fOurDragStart, sCurrentDragInfo->fOurDragEnd);
772 }
773 else {
774 // for a very short click - just treat it as a regular click - changing the
775 // selection to an insertion point where the user clicked.
776 size_t ignored = 0;
777 (void)this->ProcessSimpleClick (this->fMouseTrackingLastPoint, 1, false, &ignored);
778 }
779 } break;
780 case DROPEFFECT_MOVE: {
781 /*
782 * delete the original text on a MOVE
783 */
784 TextInteractor::InteractiveModeUpdater iuMode{*this};
785 AssertNotNull (sCurrentDragInfo);
786 TextInteractor::UndoableContextHelper undoContext (
787 *this, sCurrentDragInfo->fWeRecievedDrop ? SDKString{} : GetCommandNames ().fDragCommandName,
788 sCurrentDragInfo->fOrigSelection.GetStart (), sCurrentDragInfo->fOrigSelection.GetEnd (), true);
789 {
790 TextInteractor::InteractiveReplace_ (undoContext.GetUndoRegionStart (), undoContext.GetUndoRegionEnd (),
791 LED_TCHAR_OF (""), 0, false, false, eDefaultUpdate);
792 }
793 undoContext.CommandComplete (sCurrentDragInfo->fOrigSelection.GetEnd ());
794 } break;
795 default: {
796 // we do nothing then - I think....
797 }
798 }
799
800 // must do here, even if NOT a MOVE - cuz we skipped this in the OnDrop code...
801 this->BreakInGroupedCommands ();
802 }
803 catch (...) {
804 delete sCurrentDragInfo;
805 sCurrentDragInfo = NULL;
806 throw;
807 }
808
809 delete sCurrentDragInfo;
810 sCurrentDragInfo = NULL;
811 }
812 template <typename BASECLASS>
813 void Led_MFC_DragAndDropWindow<BASECLASS>::HandleSharedDragOverUpdateSelCode ()
814 {
815 using TextInteractor::eImmediateUpdate;
816 CClientDC dc (this);
817 if (fPrevDropEffect != DROPEFFECT_NONE) {
818 // erase previous focus rect
819 dc.DrawFocusRect (CRect (fDragPoint, fDragSize));
820 }
821
822 size_t newPos = this->GetCharAtClickLocation (AsLedPoint (fDragPoint));
823
824 // Auto-scroll if necessary...
825 if (newPos < this->GetMarkerPositionOfStartOfWindow ()) {
826 this->ScrollByIfRoom (-1, eImmediateUpdate);
827 }
828 else if (newPos > this->GetMarkerPositionOfEndOfWindow ()) {
829 this->ScrollByIfRoom (1, eImmediateUpdate);
830 }
831
832 if (fPrevDropEffect != DROPEFFECT_NONE) {
833 // draw new focus rect
834 dc.DrawFocusRect (CRect (fDragPoint, fDragSize));
835 }
836 }
837 template <typename BASECLASS>
838 DROPEFFECT Led_MFC_DragAndDropWindow<BASECLASS>::HelperDragEnter (COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
839 {
840 // We allow dropping any time - I think... - See page 444 of MSVC4.0 Visual C++ Tutorial for hints on how to check if we accept...
841 this->StartDragAutoscrollTimer ();
842 if (not GetObjectInfo (pDataObject, &fDragSize, &fDragOffset)) {
843 return DROPEFFECT_NONE;
844 }
845 CClientDC dc (NULL);
846 dc.HIMETRICtoDP (&fDragSize);
847 dc.HIMETRICtoDP (&fDragOffset);
848 DROPEFFECT result = this->HelperDragOver (pDataObject, dwKeyState, point);
849 return result;
850 }
851 template <typename BASECLASS>
852 DROPEFFECT Led_MFC_DragAndDropWindow<BASECLASS>::HelperDragOver (COleDataObject* /*pDataObject*/, DWORD dwKeyState, CPoint point)
853 {
854 using TextInteractor::eImmediateUpdate;
855 point -= fDragOffset; // adjust target rect by cursor offset
856
857 // See See page 444 of MSVC4.0 Visual C++ Tutorial for hints on how to check if we accept...
858
859 // now do draw of hilite...
860 DROPEFFECT de = DROPEFFECT_NONE;
861
862 if ((dwKeyState & (MK_CONTROL | MK_SHIFT)) == (MK_CONTROL | MK_SHIFT)) {
863 de = DROPEFFECT_NONE; // we don't support linking...
864 }
865 else if ((dwKeyState & MK_CONTROL) == MK_CONTROL) {
866 de = DROPEFFECT_COPY;
867 }
868 else if ((dwKeyState & MK_ALT) == MK_ALT) {
869 de = DROPEFFECT_MOVE;
870 }
871 else {
872 de = DROPEFFECT_MOVE; // an unfortunate choice, but windows defaults to this apparently...
873 }
874
875 if (point != fDragPoint) {
876 // cursor has moved
877 CClientDC dc (this);
878 if (fPrevDropEffect != DROPEFFECT_NONE) {
879 // erase previous focus rect
880 dc.DrawFocusRect (CRect (fDragPoint, fDragSize));
881 }
882
883 size_t newPos = this->GetCharAtClickLocation (AsLedPoint (point));
884
885 // Disalow dragging selection ontop of itself...
886 if (sCurrentDragInfo != NULL and sCurrentDragInfo->fLedMFCView == this and
887 (newPos >= sCurrentDragInfo->fOurDragStart and newPos <= sCurrentDragInfo->fOurDragEnd)) {
888 this->SetSelection (sCurrentDragInfo->fOurDragStart, sCurrentDragInfo->fOurDragEnd);
889 this->Update ();
890 fPrevDropEffect = DROPEFFECT_NONE;
891 return DROPEFFECT_NONE;
892 }
893
894 // either scroll, or adjust the selection...
895 if (newPos < this->GetMarkerPositionOfStartOfWindow ()) {
896 this->ScrollByIfRoom (-1, eImmediateUpdate);
897 }
898 else if (newPos > this->GetMarkerPositionOfEndOfWindow ()) {
899 this->ScrollByIfRoom (1, eImmediateUpdate);
900 }
901
902 if (newPos >= this->GetMarkerPositionOfStartOfWindow () and newPos <= this->GetMarkerPositionOfEndOfWindow ()) {
903 this->SetSelection (newPos, newPos);
904 this->Update ();
905 }
906
907 fPrevDropEffect = de;
908 if (fPrevDropEffect != DROPEFFECT_NONE) {
909 // draw new focus rect
910 fDragPoint = point;
911 dc.DrawFocusRect (CRect (fDragPoint, fDragSize));
912 }
913 }
914
915 return de;
916 }
917 template <typename BASECLASS>
918 BOOL Led_MFC_DragAndDropWindow<BASECLASS>::HelperDrop (COleDataObject* pDataObject, DROPEFFECT /*dropEffect*/, CPoint /*point*/)
919 {
920 using namespace Stroika::Foundation;
921 RequireNotNull (pDataObject);
922
923 // Cleanup focus rect...
924 HelperDragLeave ();
925
926 if (sCurrentDragInfo != NULL and sCurrentDragInfo->fLedMFCView == this) {
927 sCurrentDragInfo->fWeRecievedDrop = true;
928 }
929
930#if 0
931 // debugging hack- leave in for now in case helpful to see whats in drop package...
932 // LGP 960502
933 {
934 pDataObject->BeginEnumFormats ();
935 FORMATETC formatC;
936 while (pDataObject->GetNextFormat (&formatC)) {
937 char buf[1024];
938 int nChars = ::GetClipboardFormatName (formatC.cfFormat, buf, sizeof buf);
939 int barf = 1; // set breakpoint here
940 }
941 }
942#endif
943
944 CWaitCursor busy;
945
946 Led_MFCReaderDAndDFlavorPackage flavors (pDataObject);
947
948 bool doSmartCNP = this->GetSmartCutAndPasteMode () and flavors.GetFlavorAvailable_TEXT ();
949 TextInteractor::SmartCNPInfo smartCNPInfo;
950 if (doSmartCNP) {
951 size_t length = flavors.GetFlavorSize (kTEXTClipFormat);
952 Led_ClipFormat textFormat = kTEXTClipFormat;
953 Memory::StackBuffer<Led_tChar> buf{Memory::eUninitialized, length}; // really could use smaller buffer
954 length = flavors.ReadFlavorData (textFormat, length, buf.data ());
955 if (doSmartCNP) {
956 size_t nTChars = length / sizeof (Led_tChar);
957 if (nTChars > 0) {
958 --nTChars; // on windows, the text buffer contains a trailing NUL-byte
959 }
960 doSmartCNP = this->LooksLikeSmartPastableText (buf.data (), nTChars, &smartCNPInfo);
961 }
962 }
963
964 this->BreakInGroupedCommands ();
965
966 TextInteractor::InteractiveModeUpdater iuMode (*this);
967 size_t ucSelStart = (sCurrentDragInfo != nullptr and sCurrentDragInfo->fLedMFCView == this) ? sCurrentDragInfo->fOrigSelection.GetStart ()
968 : this->GetSelectionStart ();
969 size_t ucSelEnd = (sCurrentDragInfo != nullptr and sCurrentDragInfo->fLedMFCView == this) ? sCurrentDragInfo->fOrigSelection.GetEnd ()
970 : this->GetSelectionEnd ();
971 TextInteractor::UndoableContextHelper undoContext (*this,
972 (sCurrentDragInfo != nullptr and sCurrentDragInfo->fLedMFCView == this)
973 ? GetCommandNames ().fDragNDropCommandName
974 : GetCommandNames ().fDropCommandName,
975 this->GetSelectionStart (), this->GetSelectionEnd (), ucSelStart, ucSelEnd, false);
976 {
977 try {
978 this->InternalizeBestFlavor (flavors);
979 }
980 catch (...) {
981#if _MFC_VER > 0x0E00
982// Known broken in 0x0421 and 0x0600 anx 0x700 (MSVC.Net), and 0x710 (MSVC.NET 2003), and 0x0A00 (MSVC.net 2010),
983// and 0x0B00 = Microsoft Foundation Classes version 11.00
984// and 0x0C00 = Microsoft Foundation Classes version 12.00
985// and 0x0E00 = MFC included with Visual Studio.net 2017
986#pragma message("See if MFC has fixed this bug yet")
987#endif
988 // Cannot re-throw here, due to MFC bug in COleDropTarget::XDropTarget::Drop (), where
989 // it fails to do a RELEASE() call in case we throw here. Returning FALSE still signifies the drop fialed, but
990 // then the calling APP may not see a good message about what failed. Too bad.
991 return false;
992 throw;
993 }
994 if (doSmartCNP) {
995 this->OptionallyAddExtraSpaceForSmartCutAndPasteModeAdds (undoContext.GetUndoRegionStart (), smartCNPInfo);
996 }
997 }
998 undoContext.CommandComplete ();
999
1000 // If WE INITED DRAG - don't do break here, do it in HandleDragSelect () so it can incorporate a DELETE TEXT on MOVE...
1001 if (sCurrentDragInfo == nullptr or sCurrentDragInfo->fLedMFCView != this) {
1002 this->BreakInGroupedCommands ();
1003 }
1004
1005 return true;
1006 }
1007 template <typename BASECLASS>
1008 void Led_MFC_DragAndDropWindow<BASECLASS>::HelperDragLeave ()
1009 {
1010 StopDragAutoscrollTimer ();
1011 if (fPrevDropEffect != DROPEFFECT_NONE) {
1012 CClientDC dc (this);
1013 // erase previous focus rect
1014 dc.DrawFocusRect (CRect (fDragPoint, fDragSize));
1015 fPrevDropEffect = DROPEFFECT_NONE;
1016 }
1017 }
1018 template <typename BASECLASS>
1019 bool Led_MFC_DragAndDropWindow<BASECLASS>::GetObjectInfo (COleDataObject* pDataObject, CSize* pSize, CSize* pOffset)
1020 {
1021 RequireNotNull (pDataObject);
1022 RequireNotNull (pSize);
1023 RequireNotNull (pOffset);
1024
1025 static CLIPFORMAT kObjectDescriptorFormatTag = (CLIPFORMAT)::RegisterClipboardFormat (_T("Object Descriptor"));
1026
1027 HGLOBAL hObjDesc = pDataObject->GetGlobalData (kObjectDescriptorFormatTag);
1028 if (hObjDesc == nullptr) {
1029 *pSize = CSize{0, 0};
1030 *pOffset = CSize{0, 0};
1031 return false;
1032 }
1033 else {
1034 LPOBJECTDESCRIPTOR pObjDesc = (LPOBJECTDESCRIPTOR)::GlobalLock (hObjDesc);
1035 if (pObjDesc == nullptr) {
1036 memset (pSize, 0, sizeof (*pSize));
1037 memset (pOffset, 0, sizeof (*pOffset));
1038 }
1039 else {
1040 pSize->cx = (int)pObjDesc->sizel.cx;
1041 pSize->cy = (int)pObjDesc->sizel.cy;
1042 pOffset->cx = (int)pObjDesc->pointl.x;
1043 pOffset->cy = (int)pObjDesc->pointl.y;
1044 }
1045 ::GlobalUnlock (hObjDesc);
1046 ::GlobalFree (hObjDesc);
1047 return true;
1048 }
1049 }
1050 template <typename BASECLASS>
1051 void Led_MFC_DragAndDropWindow<BASECLASS>::StartDragAutoscrollTimer ()
1052 {
1053 Assert (fDragAutoScrollTimerID == 0); // not sure about this - just for debug sake??? - LGP 960530
1054 if (fDragAutoScrollTimerID == 0) {
1055 //const int kTimeout = 25; // 25 milliseconds - update autoscroll every 1/40
1056 const int kTimeout = 20; // 20 milliseconds - update autoscroll every 1/50
1057 // second.
1058 Verify ((fDragAutoScrollTimerID = this->SetTimer (eAutoscrolling4DragTimerEventID, kTimeout, NULL)) != 0);
1059 }
1060 }
1061 template <typename BASECLASS>
1062 void Led_MFC_DragAndDropWindow<BASECLASS>::StopDragAutoscrollTimer ()
1063 {
1064 if (fDragAutoScrollTimerID != 0) {
1065 Verify (this->KillTimer (eAutoscrolling4DragTimerEventID));
1066 fDragAutoScrollTimerID = 0;
1067 }
1068 }
1069 template <typename BASECLASS>
1070 void Led_MFC_DragAndDropWindow<BASECLASS>::OnTimer (UINT_PTR nEventID)
1071 {
1072 if (nEventID == eAutoscrolling4DragTimerEventID) {
1073 this->HandleSharedDragOverUpdateSelCode ();
1074 }
1075 else {
1076 inherited::OnTimer (nEventID);
1077 }
1078 }
1079 template <typename BASECLASS>
1080 const AFX_MSGMAP* Led_MFC_DragAndDropWindow<BASECLASS>::GetMessageMap () const
1081 {
1082 return GetThisMessageMap ();
1083 }
1084 template <typename BASECLASS>
1085 const AFX_MSGMAP* PASCAL Led_MFC_DragAndDropWindow<BASECLASS>::GetThisMessageMap ()
1086 {
1087 using ThisClass = Led_MFC_DragAndDropWindow<BASECLASS>;
1088 using TheBaseClass = BASECLASS;
1089 DISABLE_COMPILER_MSC_WARNING_START (4407) // Not sure this is safe to ignore but I think it is due to qStroika_Frameworks_Led_MFCRequiresCWndLeftmostBaseClass
1090 static const AFX_MSGMAP_ENTRY _messageEntries[] = {ON_WM_CREATE () ON_WM_TIMER (){0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0}};
1091 DISABLE_COMPILER_MSC_WARNING_END (4407)
1092 static const AFX_MSGMAP messageMap = {&TheBaseClass::GetThisMessageMap, &_messageEntries[0]};
1093 return &messageMap;
1094 }
1095
1096 // class Led_MFC_CViewHelper<BASECLASS>
1097 template <typename BASECLASS>
1098 Led_MFC_CViewHelper<BASECLASS>::Led_MFC_CViewHelper ()
1099 : inherited ()
1100 ,
1101 // NB: CTOR for TWIPS_Rect is TOP/LEFT/HEIGHT/WIDTH, so we set height/width to zero to get same TLBR.
1102 fPrintMargins (TWIPS_Rect (TWIPS{1440}, TWIPS{1440}, TWIPS{0}, TWIPS{0}))
1103 , fPrintInfo{nullptr}
1104 {
1105 }
1106 template <typename BASECLASS>
1107 Led_MFC_CViewHelper<BASECLASS>::~Led_MFC_CViewHelper ()
1108 {
1109 Assert (fPrintInfo == nullptr);
1110 }
1111 template <typename BASECLASS>
1112 /*
1113 @METHOD: Led_MFC_CViewHelper<BASECLASS>::GetPrintMargins
1114 @DESCRIPTION: <p>Return the print margins. These are used by @'Led_MFC_CViewHelper<BASECLASS>::CalculatePrintingRect'.
1115 See also @'Led_MFC_CViewHelper<BASECLASS>::SetPrintMargins'.
1116 */
1117 TWIPS_Rect Led_MFC_CViewHelper<BASECLASS>::GetPrintMargins () const
1118 {
1119 return fPrintMargins;
1120 }
1121 template <typename BASECLASS>
1122 /*
1123 @METHOD: Led_MFC_CViewHelper<BASECLASS>::SetPrintMargins
1124 @DESCRIPTION: <p>See also @'Led_MFC_CViewHelper<BASECLASS>::GetPrintMargins'.
1125 */
1126 void Led_MFC_CViewHelper<BASECLASS>::SetPrintMargins (const TWIPS_Rect& printMargins)
1127 {
1128 fPrintMargins = printMargins;
1129 }
1130 template <typename BASECLASS>
1131 /*
1132 @METHOD: Led_MFC_CViewHelper<BASECLASS>::OnPreparePrinting
1133 @DESCRIPTION: Hook the MFC OnPreparePrinting () method to handle printing in the standard MFC fasion.
1134 Don't call this directly.
1135 */
1136 BOOL Led_MFC_CViewHelper<BASECLASS>::OnPreparePrinting (CPrintInfo* pInfo)
1137 {
1138 // default preparation
1139 return this->DoPreparePrinting (pInfo);
1140 }
1141 template <typename BASECLASS>
1142 /*
1143 @METHOD: Led_MFC_CViewHelper<BASECLASS>::OnBeginPrinting
1144 @DESCRIPTION: Hook the MFC OnBeginPrinting () method to handle printing in the standard MFC fasion.
1145 Also, keep track of some internals we will use later in printing, and setup SetForceAllRowsShowing
1146 so when we print the last page, we can see lots of nice whatspace at the end. Don't call this directly.
1147 */
1148 void Led_MFC_CViewHelper<BASECLASS>::OnBeginPrinting (CDC* pDC, CPrintInfo* pInfo)
1149 {
1150 // THIS CODE IS KINDOF HACKISH - SHOULD HAVE A PAGENATE STAGE/FUNCTION!!! TO FILL THIS ARRAY!!!
1151 Assert (fPrintInfo == nullptr);
1152 BASECLASS::OnBeginPrinting (pDC, pInfo);
1153 fPrintInfo = new PrintInfo (*this, pDC, this->GetWindowRect (), this->GetMarkerPositionOfStartOfWindow (), this->GetForceAllRowsShowing ());
1154 this->SetForceAllRowsShowing (false);
1155 }
1156 template <typename BASECLASS>
1157 void Led_MFC_CViewHelper<BASECLASS>::OnPrint (CDC* pDC, CPrintInfo* /*pInfo*/)
1158 {
1159 AssertNotNull (fPrintInfo);
1160 // Consider different print loop - maybe different print-oriented entry in TextImager?
1161 // That doesn't have todo with scrolling? Just DrawFromSize_tOffset? Maybe - into rect.
1162 // Make the MRTI::Draw() vector to that?
1163 ASSERT_VALID (pDC);
1164 Led_MFC_TabletFromCDC tablet (pDC);
1165 typename BASECLASS::TemporarilyUseTablet tmpUseTablet{*this, tablet, BASECLASS::TemporarilyUseTablet::eDontDoTextMetricsChangedCall};
1166 CRect boundsRect = CRect (0, 0, 0, 0);
1167 Verify (pDC->GetClipBox (&boundsRect) != ERROR);
1168 this->Draw (AsLedRect (boundsRect), true);
1169 }
1170 template <typename BASECLASS>
1171 void Led_MFC_CViewHelper<BASECLASS>::OnEndPrinting (CDC* pDC, CPrintInfo* pInfo)
1172 {
1173 if (fPrintInfo == nullptr) {
1174 // Can be NULL if print fails, cuz no printer installed
1175 BASECLASS::OnEndPrinting (pDC, pInfo);
1176 }
1177 else {
1178 this->SetForceAllRowsShowing (fPrintInfo->fSavedForceAllRowsFlag);
1179 this->SetWindowRect (fPrintInfo->fOldWindowRect);
1180 this->SetTopRowInWindowByMarkerPosition (fPrintInfo->fSavedScrollPos);
1181 delete fPrintInfo;
1182 fPrintInfo = nullptr;
1183 BASECLASS::OnEndPrinting (pDC, pInfo);
1184 }
1185 }
1186 template <typename BASECLASS>
1187 void Led_MFC_CViewHelper<BASECLASS>::OnPrepareDC (CDC* pDC, CPrintInfo* pInfo)
1188 {
1189 if (pInfo != NULL and pDC->IsPrinting ()) { // For some STUPID reason, MFC calls this even if we aren't printing...
1190 {
1191 WindowDC screenDC (NULL);
1192 (void)pDC->SetMapMode (MM_ANISOTROPIC);
1193 (void)pDC->SetWindowExt (screenDC.GetDeviceCaps (LOGPIXELSX), screenDC.GetDeviceCaps (LOGPIXELSY));
1194 (void)pDC->SetViewportExt (pDC->GetDeviceCaps (LOGPIXELSX), pDC->GetDeviceCaps (LOGPIXELSY));
1195 // I REMOVED calls to SetWindowRect/TabletChangedMetrics for WYSYWIG (SPR#0869),
1196 // This created a new problem - SPR#1079 - which is now fixed (or largely worked around here).
1197 // Probably there is still a real latent problem inside TabletChangedMetrics - but I don't
1198 // need to debug that now, and this whole thing will go away if I rewrite the printing code
1199 // after 3.0 - as is anticipated.
1200 // I changed the args to CalculateWindowRect() to accomodate this bugfix.
1201 //
1202 Led_Rect oldWR = this->GetWindowRect ();
1203 Led_Rect newWR = this->CalculatePrintingRect (pDC);
1204 this->SetWindowRect (newWR);
1205 }
1206 CView::OnPrepareDC (pDC, pInfo);
1207 if (fPrintInfo->fWindowStarts.size () == 0) {
1208 fPrintInfo->fWindowStarts.push_back (0);
1209 this->SetTopRowInWindowByMarkerPosition (0, TextInteractor::eNoUpdate);
1210 }
1211 pInfo->m_bContinuePrinting = true; // Assume scroll forward succeeded
1212 // First page into our fWindowStarts cache enuf pages to satisfy this 'goto page' request. NB:
1213 // In Print (page n..m) requests - this can be starting well past fWindowStarts.size () - contrary
1214 // to earlier - incorrect - Led comments - LGP 981007
1215 while (fPrintInfo->fWindowStarts.size () < pInfo->m_nCurPage) {
1216 // advanced one page...
1217 if (this->GetMarkerPositionOfEndOfWindow () == this->GetTextStore ().GetEnd ()) {
1218 pInfo->m_bContinuePrinting = false; // scroll forward failed
1219 return;
1220 }
1221 this->SetTopRowInWindowByMarkerPosition (this->FindNextCharacter (this->GetMarkerPositionOfEndOfWindow ()), TextInteractor::eNoUpdate);
1222 size_t newStart = this->GetMarkerPositionOfStartOfWindow ();
1223 if (newStart == fPrintInfo->fWindowStarts.back ()) {
1224 pInfo->m_bContinuePrinting = false; // scroll forward failed
1225 return;
1226 }
1227 else {
1228 fPrintInfo->fWindowStarts.push_back (newStart);
1229 }
1230 }
1231 // scroll forward/back to some page in our (now filled in cache) page list
1232 this->SetTopRowInWindowByMarkerPosition (fPrintInfo->fWindowStarts[pInfo->m_nCurPage - 1]);
1233 if (this->GetMarkerPositionOfEndOfWindow () == this->GetTextStore ().GetEnd ()) {
1234 pInfo->SetMaxPage (pInfo->m_nCurPage);
1235 return;
1236 }
1237 }
1238 }
1239 template <typename BASECLASS>
1240 /*
1241 @METHOD: Led_MFC_CViewHelper<BASECLASS>::CalculatePrintingRect
1242 @DESCRIPTION: Hook function to change the default size Led will use for printing. Defautlts to
1243 FULL page. Override to inset for margins, and/or headers/footers, or call @'Led_MFC_CViewHelper<BASECLASS>::SetPrintMargins'.
1244 <p>Don't call directly. Just called after DC setup from @'Led_MFC_CViewHelper<BASECLASS>::OnPrepareDC'.</p>
1245 <p>See also @'Led_MFC_CViewHelper<BASECLASS>::GetPrintMargins' to specify the margins that are used by this
1246 routine by default.</p>
1247 */
1248 Led_Rect Led_MFC_CViewHelper<BASECLASS>::CalculatePrintingRect (CDC* pDC) const
1249 {
1250 RequireNotNull (pDC);
1251 /*
1252 * See SPR#1079, and SPR#1153 about whats going on here.
1253 */
1254 CRect winRect = CRect (0, 0, pDC->GetDeviceCaps (HORZRES), pDC->GetDeviceCaps (VERTRES));
1255 pDC->DPtoLP (&winRect);
1256 Led_Rect useRect = AsLedRect (winRect);
1257 Led_Rect marginRect = Led_MFC_TabletFromCDC (pDC)->CvtFromTWIPS (fPrintMargins);
1258 useRect = Led_Rect (useRect.GetTop () + marginRect.GetTop (), useRect.GetLeft () + marginRect.GetLeft (),
1259 useRect.GetHeight () - (marginRect.GetTop () + marginRect.GetBottom ()),
1260 useRect.GetWidth () - (marginRect.GetLeft () + marginRect.GetRight ()));
1261 return useRect;
1262 }
1263 template <typename BASECLASS>
1264 void Led_MFC_CViewHelper<BASECLASS>::InvalidateScrollBarParameters ()
1265 {
1266 if (fPrintInfo == nullptr) {
1267 inherited::InvalidateScrollBarParameters ();
1268 }
1269 }
1270 template <typename BASECLASS>
1271 /*
1272 @METHOD: Led_MFC_CViewHelper<BASECLASS>::UpdateScrollBars
1273 @DESCRIPTION: Avoid errors updating sbars while printing.
1274 */
1275 void Led_MFC_CViewHelper<BASECLASS>::UpdateScrollBars ()
1276 {
1277 if (fPrintInfo != nullptr) {
1278 return; // ignore while in print mode...
1279 }
1280 inherited::UpdateScrollBars ();
1281 }
1282 template <typename BASECLASS>
1283 /*
1284 @METHOD: Led_MFC_CViewHelper<BASECLASS>::DeleteContents
1285 @DESCRIPTION: Hook the MFC DeleteContents () routine, and simulate the user having deleted all the text in the
1286 buffer.
1287 */
1288 void Led_MFC_CViewHelper<BASECLASS>::DeleteContents ()
1289 {
1290 ASSERT_VALID (this);
1291 AssertNotNull (this->m_hWnd);
1292 this->SetWindowText (nullptr);
1293 ASSERT_VALID (this);
1294 }
1295 template <typename BASECLASS>
1296 void Led_MFC_CViewHelper<BASECLASS>::Serialize (CArchive& ar)
1297 {
1298 // Probably not the right thing todo, but a simple enuf hack for now - LGP 950511
1299 this->SerializeRaw (ar);
1300 }
1301 template <typename BASECLASS>
1302 void Led_MFC_CViewHelper<BASECLASS>::SerializeRaw (CArchive& ar)
1303 {
1304 ASSERT_VALID (this);
1305 AssertNotNull (this->m_hWnd);
1306 if (ar.IsStoring ()) {
1307 this->WriteToArchive (ar);
1308 }
1309 else {
1310 CFile* file = ar.GetFile ();
1311 ASSERT_VALID (file);
1312 DWORD dwLen = static_cast<DWORD> (file->GetLength ()); // maybe should subtract current offset?
1313 this->ReadFromArchive (ar, (UINT)dwLen);
1314 }
1315 ASSERT_VALID (this);
1316 }
1317 template <typename BASECLASS>
1318 void Led_MFC_CViewHelper<BASECLASS>::ReadFromArchive (CArchive& ar, UINT nLen)
1319 {
1320 using namespace Stroika::Foundation;
1321 ASSERT_VALID (this);
1322
1323 Memory::StackBuffer<Led_tChar> buf{Memory::eUninitialized, nLen};
1324 if (ar.Read (buf.data (), nLen * sizeof (Led_tChar)) != nLen * sizeof (Led_tChar)) {
1325 AfxThrowArchiveException (CArchiveException::endOfFile);
1326 }
1327 // Replace the editing edit buffer with the newly loaded data
1328 nLen = static_cast<UINT> (Characters::NormalizeTextToNL<Led_tChar> (buf.data (), nLen, buf.data (), nLen));
1329 if (ValidateTextForCharsetConformance (buf.data (), nLen)) {
1330 this->Replace (0, 0, buf.data (), nLen);
1331 }
1332 else {
1333 this->OnBadUserInput ();
1334 }
1335
1336 this->Invalidate ();
1337
1338 ASSERT_VALID (this);
1339 }
1340 template <typename BASECLASS>
1341 void Led_MFC_CViewHelper<BASECLASS>::WriteToArchive (CArchive& ar)
1342 {
1343 using namespace Foundation;
1344 ASSERT_VALID (this);
1345
1346 size_t nLen = this->GetLength ();
1347 Memory::StackBuffer<Led_tChar> buf{Memory::eUninitialized, nLen};
1348 this->CopyOut (0, nLen, buf.data ());
1349 Memory::StackBuffer<Led_tChar> buf2{Memory::eUninitialized, 2 * nLen};
1350 nLen = Characters::NLToNative<Led_tChar> (buf.data (), nLen, buf2.data (), 2 * nLen);
1351 ar.Write (buf2.data (), static_cast<UINT> (nLen * sizeof (Led_tChar)));
1352
1353 ASSERT_VALID (this);
1354 }
1355 template <typename BASECLASS>
1356 void Led_MFC_CViewHelper<BASECLASS>::OnLButtonDown (UINT nFlags, CPoint oPoint)
1357 {
1358 this->UpdateClickCount (Foundation::Time::GetTickCount (), AsLedPoint (oPoint));
1359
1360 if (this->m_pDocument != NULL and dynamic_cast<COleDocument*> (this->m_pDocument) != NULL) {
1361 // Any time we get a click, make sure there are no active in-place activations.
1362 // Any click anyplace outside the active item is ignored, except for deactivating
1363 // that item.
1364 AssertMember (this->m_pDocument, COleDocument); //
1365 COleDocument& doc = *(COleDocument*)this->m_pDocument;
1366 COleClientItem* pItem = doc.GetInPlaceActiveItem (this);
1367 if (pItem != NULL) {
1368 pItem->Close ();
1369 return;
1370 }
1371 }
1372
1373 if (this->GetCurClickCount () == 1 and this->IsADragSelect (AsLedPoint (oPoint))) {
1374 this->HandleDragSelect (nFlags, oPoint);
1375 }
1376 else {
1377 this->OnNormalLButtonDown (nFlags, AsLedPoint (oPoint));
1378 }
1379 }
1380 template <typename BASECLASS>
1381 DROPEFFECT Led_MFC_CViewHelper<BASECLASS>::OnDragEnter (COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
1382 {
1383 return this->HelperDragEnter (pDataObject, dwKeyState, point);
1384 }
1385 template <typename BASECLASS>
1386 DROPEFFECT Led_MFC_CViewHelper<BASECLASS>::OnDragOver (COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
1387 {
1388 return this->HelperDragOver (pDataObject, dwKeyState, point);
1389 }
1390 template <typename BASECLASS>
1391 BOOL Led_MFC_CViewHelper<BASECLASS>::OnDrop (COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point)
1392 {
1393 return this->HelperDrop (pDataObject, dropEffect, point);
1394 }
1395 template <typename BASECLASS>
1396 void Led_MFC_CViewHelper<BASECLASS>::OnDragLeave ()
1397 {
1398 this->HelperDragLeave ();
1399 }
1400 template <typename BASECLASS>
1401 void Led_MFC_CViewHelper<BASECLASS>::OnPaint ()
1402 {
1403 CView::OnPaint (); // don't use inherited/Led_MFC_CViewHelper<BASECLASS>_Helper<T> version - cuz misses some MFC hooks
1404 }
1405 template <typename BASECLASS>
1406 /*
1407 @METHOD: Led_MFC_CViewHelper<BASECLASS>::OnDraw
1408 @DESCRIPTION: Hook the MFC OnDraw () method to invoke the Led drawing mechanism, and redisplay the window.
1409 */
1410 void Led_MFC_CViewHelper<BASECLASS>::OnDraw (CDC* pDC)
1411 {
1412 ASSERT_VALID (pDC);
1413
1414 /*
1415 * Since we currently use the same textimager for printing as for display, we will screw
1416 * up all our cached info for line breaks etc if we display while we are printing.
1417 * If it is desired to make this work then we must use a NEW imager (as with LedIt! PowerPlant)
1418 * to print to.
1419 */
1420 if (fPrintInfo != nullptr) {
1421 return;
1422 }
1423
1424 CRect boundsRect = CRect (0, 0, 0, 0);
1425 Verify (pDC->GetClipBox (&boundsRect) != ERROR);
1426 this->WindowDrawHelper (Led_MFC_TabletFromCDC (pDC), AsLedRect (boundsRect), false);
1427 }
1428 template <typename BASECLASS>
1429 int Led_MFC_CViewHelper<BASECLASS>::OnCreate (::LPCREATESTRUCT lpCreateStruct)
1430 {
1431 if (inherited::OnCreate (lpCreateStruct) != 0) {
1432 return -1; // failed to create
1433 }
1434 this->TabletChangedMetrics (); // maybe should catch failures here, and return -1?
1435 return 0; // sucess
1436 }
1437 template <typename BASECLASS>
1438 void Led_MFC_CViewHelper<BASECLASS>::OnVScroll (UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
1439 {
1440 if (this->m_pDocument != NULL and dynamic_cast<COleDocument*> (this->m_pDocument) != NULL) {
1441 // Don't allow scrolling while there is an in-place active item.
1442 // Wish we had a better interface for this... Maybe we should be deactivating
1443 // SBARS when we activate item??? For now, interpret scroll attempt as a request
1444 // to deactivate...
1445 // LGP 960530
1446 AssertMember (this->m_pDocument, COleDocument);
1447 COleDocument& doc = *(COleDocument*)this->m_pDocument;
1448 COleClientItem* pItem = doc.GetInPlaceActiveItem (this);
1449 if (pItem != NULL) {
1450 pItem->Close ();
1451 return;
1452 }
1453 }
1454 inherited::OnVScroll (nSBCode, nPos, pScrollBar);
1455 }
1456 template <typename BASECLASS>
1457 void Led_MFC_CViewHelper<BASECLASS>::OnHScroll (UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
1458 {
1459 if (this->m_pDocument != NULL and dynamic_cast<COleDocument*> (this->m_pDocument) != NULL) {
1460 // Don't allow scrolling while there is an in-place active item.
1461 // Wish we had a better interface for this... Maybe we should be deactivating
1462 // SBARS when we activate item??? For now, interpret scroll attempt as a request
1463 // to deactivate...
1464 // LGP 960530
1465 AssertMember (this->m_pDocument, COleDocument); //
1466 COleDocument& doc = *(COleDocument*)this->m_pDocument;
1467 COleClientItem* pItem = doc.GetInPlaceActiveItem (this);
1468 if (pItem != NULL) {
1469 pItem->Close ();
1470 return;
1471 }
1472 }
1473 inherited::OnHScroll (nSBCode, nPos, pScrollBar);
1474 }
1475 template <typename BASECLASS>
1476 const AFX_MSGMAP* Led_MFC_CViewHelper<BASECLASS>::GetMessageMap () const
1477 {
1478 return GetThisMessageMap ();
1479 }
1480 template <typename BASECLASS>
1481 const AFX_MSGMAP* PASCAL Led_MFC_CViewHelper<BASECLASS>::GetThisMessageMap ()
1482 {
1483 using ThisClass = Led_MFC_CViewHelper<BASECLASS>;
1484 using TheBaseClass = BASECLASS;
1485 DISABLE_COMPILER_MSC_WARNING_START (4407) // Not sure this is safe to ignore but I think it is due to qStroika_Frameworks_Led_MFCRequiresCWndLeftmostBaseClass
1486 static const AFX_MSGMAP_ENTRY _messageEntries[] = {ON_WM_PAINT () ON_WM_LBUTTONDOWN () ON_WM_CREATE () ON_WM_VSCROLL ()
1487 ON_WM_HSCROLL (){0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0}};
1488 DISABLE_COMPILER_MSC_WARNING_END (4407)
1489 static const AFX_MSGMAP messageMap = {&TheBaseClass::GetThisMessageMap, &_messageEntries[0]};
1490 return &messageMap;
1491 }
1492
1493 // class Led_MFC_ExceptionHandlerHelper<BASECLASS>
1494 template <typename BASECLASS>
1495 /*
1496 @METHOD: Led_MFC_ExceptionHandlerHelper<BASECLASS>::HandleException
1497 @DESCRIPTION: Override this to provide different exception handling. By default, this calls @'Led_BeepNotify'.
1498 */
1499 void Led_MFC_ExceptionHandlerHelper<BASECLASS>::HandleException () const
1500 {
1501 Led_BeepNotify ();
1502 }
1503 template <typename BASECLASS>
1504 void Led_MFC_ExceptionHandlerHelper<BASECLASS>::OnChar (UINT nChar, UINT nRepCnt, UINT nFlags)
1505 {
1506 try {
1507 inherited::OnChar (nChar, nRepCnt, nFlags);
1508 }
1509 catch (...) {
1510 this->HandleException ();
1511 }
1512 }
1513 template <typename BASECLASS>
1514 LRESULT Led_MFC_ExceptionHandlerHelper<BASECLASS>::OnIMEChar (WPARAM wParam, LPARAM lParam)
1515 {
1516 try {
1517 return inherited::OnIMEChar (wParam, lParam);
1518 }
1519 catch (...) {
1520 this->HandleException ();
1521 return 0;
1522 }
1523 }
1524 template <typename BASECLASS>
1525 void Led_MFC_ExceptionHandlerHelper<BASECLASS>::OnKeyDown (UINT nChar, UINT nRepCnt, UINT nFlags)
1526 {
1527 try {
1528 inherited::OnKeyDown (nChar, nRepCnt, nFlags);
1529 }
1530 catch (...) {
1531 this->HandleException ();
1532 }
1533 }
1534 template <typename BASECLASS>
1535 LRESULT Led_MFC_ExceptionHandlerHelper<BASECLASS>::OnMsgPaste (WPARAM wParam, LPARAM lParam)
1536 {
1537 try {
1538 return inherited::OnMsgPaste (wParam, lParam);
1539 }
1540 catch (...) {
1541 this->HandleException ();
1542 return 0;
1543 }
1544 }
1545 template <typename BASECLASS>
1546 void Led_MFC_ExceptionHandlerHelper<BASECLASS>::OnLButtonDown (UINT nFlags, CPoint oPoint)
1547 {
1548 try {
1549 inherited::OnLButtonDown (nFlags, oPoint);
1550 }
1551 catch (...) {
1552 this->HandleException ();
1553 }
1554 }
1555 template <typename BASECLASS>
1556 void Led_MFC_ExceptionHandlerHelper<BASECLASS>::OnLButtonUp (UINT nFlags, CPoint oPoint)
1557 {
1558 try {
1559 inherited::OnLButtonUp (nFlags, oPoint);
1560 }
1561 catch (...) {
1562 this->HandleException ();
1563 }
1564 }
1565 template <typename BASECLASS>
1566 void Led_MFC_ExceptionHandlerHelper<BASECLASS>::OnLButtonDblClk (UINT nFlags, CPoint oPoint)
1567 {
1568 try {
1569 inherited::OnLButtonDblClk (nFlags, oPoint);
1570 }
1571 catch (...) {
1572 this->HandleException ();
1573 }
1574 }
1575 template <typename BASECLASS>
1576 BOOL Led_MFC_ExceptionHandlerHelper<BASECLASS>::OnCmdMsg (UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
1577 {
1578 try {
1579 return inherited::OnCmdMsg (nID, nCode, pExtra, pHandlerInfo);
1580 }
1581 catch (...) {
1582 this->HandleException ();
1583 return 1;
1584 }
1585 }
1586 template <typename BASECLASS>
1587 const AFX_MSGMAP* Led_MFC_ExceptionHandlerHelper<BASECLASS>::GetMessageMap () const
1588 {
1589 return GetThisMessageMap ();
1590 }
1591 template <typename BASECLASS>
1592 const AFX_MSGMAP* PASCAL Led_MFC_ExceptionHandlerHelper<BASECLASS>::GetThisMessageMap ()
1593 {
1594 using ThisClass = Led_MFC_ExceptionHandlerHelper<BASECLASS>;
1595 using TheBaseClass = BASECLASS;
1596 static const AFX_MSGMAP_ENTRY _messageEntries[] = {ON_WM_CHAR () ON_MESSAGE (WM_IME_CHAR, &OnIMEChar) ON_WM_KEYDOWN () ON_MESSAGE (
1597 WM_PASTE, &OnMsgPaste) ON_WM_LBUTTONDOWN () ON_WM_LBUTTONUP () ON_WM_LBUTTONDBLCLK (){0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0}};
1598 static const AFX_MSGMAP messageMap = {&TheBaseClass::GetThisMessageMap, &_messageEntries[0]};
1599 return &messageMap;
1600 }
1601
1602 // class Led_MFC_X<ChosenInteractor,LEDMFC>
1603 template <typename ChosenInteractor, typename LEDMFC>
1604 inline Led_MFC_X<ChosenInteractor, LEDMFC>::Led_MFC_X ()
1605 : ChosenInteractor ()
1606 , LEDMFC ()
1607 {
1608 }
1609 /*
1610 @METHOD: Led_MFC_X<ChosenInteractor,LEDMFC>::AboutToUpdateText
1611 @DESCRIPTION: Override to handle mixin ambiguity.
1612 */
1613 template <typename ChosenInteractor, typename LEDMFC>
1614 void Led_MFC_X<ChosenInteractor, LEDMFC>::AboutToUpdateText (const MarkerOwner::UpdateInfo& updateInfo)
1615 {
1616 LEDMFC::AboutToUpdateText (updateInfo);
1617 ChosenInteractor::AboutToUpdateText (updateInfo);
1618 }
1619 /*
1620 @METHOD: Led_MFC_X<ChosenInteractor,LEDMFC>::DidUpdateText
1621 @DESCRIPTION: Override to handle mixin ambiguity.
1622 */
1623 template <typename ChosenInteractor, typename LEDMFC>
1624 void Led_MFC_X<ChosenInteractor, LEDMFC>::DidUpdateText (const MarkerOwner::UpdateInfo& updateInfo) noexcept
1625 {
1626 LEDMFC::DidUpdateText_ (updateInfo);
1627 ChosenInteractor::DidUpdateText (updateInfo);
1628 }
1629
1630 // FUNCTION Led_GetTextExtent ()
1631 /*
1632 @METHOD: Led_GetTextExtent<TRIVIALWORDWRAPPEDTEXTIMAGER,SIMPLETEXTIMAGER,TEXTSTORE>
1633 @DESCRIPTION: Trivial wrapper on TrivialImager<TEXTSTORE,IMAGER> etc, except it handles
1634 case of word wrapping as a parameter. So this is roughly a replacement for the Win32 SDK
1635 routine GetTextExtent() - except its implemented by Led (and so UNICODE friendly, for example).
1636 <p>Note - this is done as a template - rather than directly as a function - so as to avoid forcing
1637 people who include Led_MFC from also including all these other modules required for this. There is
1638 a global function version of this function (@'Led_GetTextExtent') which will be enabled/included in
1639 your program if you define @'qSupportDrawTextGetTextExtent'.
1640 <p>See also Led_DrawText<TRIVIALWORDWRAPPEDTEXTIMAGER,SIMPLETEXTIMAGER,TEXTSTORE>
1641 */
1642 template <typename TRIVIALWORDWRAPPEDTEXTIMAGER, typename SIMPLETEXTIMAGER, typename TEXTSTORE>
1643 CSize Led_GetTextExtent (CDC* cdc, const Led_tString& text, CRect r, bool wordWrap)
1644 {
1645 RequireNotNull (cdc);
1646 Led_MFC_TabletFromCDC tmpTablet (cdc);
1647 return AsCSize (GetTextExtent<TRIVIALWORDWRAPPEDTEXTIMAGER, SIMPLETEXTIMAGER, TEXTSTORE> (tmpTablet, text, AsLedRect (r), wordWrap));
1648 }
1649
1650 // FUNCTION Led_DrawText ()
1651 /*
1652 @METHOD: Led_DrawText<TRIVIALWORDWRAPPEDTEXTIMAGER,SIMPLETEXTIMAGER,TEXTSTORE>
1653 @DESCRIPTION: Trivial wrapper on TrivialImager<TEXTSTORE,IMAGER> etc, except it handles
1654 case of word wrapping as a parameter. So this is roughly a replacement for the Win32 SDK
1655 routine DrawText () - except its implemented by Led (and so UNICODE friendly, for example).
1656 <p>Note - this is done as a template - rather than directly as a function - so as to avoid forcing
1657 people who include Led_MFC from also including all these other modules required for this. There is
1658 a global function version of this function (@'Led_DrawText') which will be enabled/included in
1659 your program if you define @'qSupportDrawTextGetTextExtent'.
1660 <p>See also Led_GetTextExtent<TRIVIALWORDWRAPPEDTEXTIMAGER,SIMPLETEXTIMAGER,TEXTSTORE>
1661 */
1662 template <typename TRIVIALWORDWRAPPEDTEXTIMAGER, typename SIMPLETEXTIMAGER, typename TEXTSTORE>
1663 void Led_DrawText (CDC* cdc, const Led_tString& text, CRect r, bool wordWrap)
1664 {
1665 RequireNotNull (cdc);
1666 Led_MFC_TabletFromCDC tmpTablet (cdc);
1667 DrawTextBox<TRIVIALWORDWRAPPEDTEXTIMAGER, SIMPLETEXTIMAGER, TEXTSTORE> (tmpTablet, text, AsLedRect (r), wordWrap);
1668 }
1669
1670 // class Led_MFC_TmpCmdUpdater
1671 inline Led_MFC_TmpCmdUpdater::Led_MFC_TmpCmdUpdater (CCmdUI* pCmdUI)
1672 : fCmdUI (pCmdUI)
1673 , fCmdNum (MFC_CommandNumberMapping::Get ().Lookup (pCmdUI->m_nID))
1674 , fEnabled (false)
1675 {
1676 RequireNotNull (fCmdUI);
1677 }
1678 inline Led_MFC_TmpCmdUpdater::operator Led_MFC_TmpCmdUpdater*()
1679 {
1680 return this;
1681 }
1682 inline Led_MFC_TmpCmdUpdater::operator CCmdUI*()
1683 {
1684 EnsureNotNull (fCmdUI);
1685 return fCmdUI;
1686 }
1687}
1688
1689CompileTimeFlagChecker_HEADER (Stroika::Frameworks::Led::Platform, qStroika_Frameworks_Led_MFCRequiresCWndLeftmostBaseClass,
1690 qStroika_Frameworks_Led_MFCRequiresCWndLeftmostBaseClass)
#define AssertNotNull(p)
Definition Assertions.h:336
#define EnsureNotNull(p)
Definition Assertions.h:343
#define qStroika_Foundation_Debug_AssertionsChecked
The qStroika_Foundation_Debug_AssertionsChecked flag determines if assertions are checked and validat...
Definition Assertions.h:49
#define RequireNotNull(p)
Definition Assertions.h:350
#define AssertMember(p, c)
Definition Assertions.h:315
#define Verify(c)
Definition Assertions.h:422
#define CompileTimeFlagChecker_HEADER(NS_PREFIX, NAME, VALUE)
CompileTimeFlagChecker_HEADER () will generate a LINK ERROR if you ever compile a header with one val...
time_point< RealtimeClock, DurationSeconds > TimePointSeconds
TimePointSeconds is a simpler approach to chrono::time_point, which doesn't require using templates e...
Definition Realtime.h:82
chrono::duration< double > DurationSeconds
chrono::duration<double> - a time span (length of time) measured in seconds, but high precision.
Definition Realtime.h:57
#define DbgTrace
Definition Trace.h:327
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
Create a format-string (see std::wformat_string or Stroika FormatString, or python 'f' strings) - a F...
basic_string< SDKChar > SDKString
Definition SDKString.h:38