80f87682e32307927cc53f9b28370fff400f466e
2 * PROJECT: PAINT for ReactOS
4 * FILE: base/applications/mspaint/textedit.cpp
5 * PURPOSE: Text editor and font chooser for the text tool
6 * PROGRAMMERS: Benedikt Freisen
9 /* INCLUDES *********************************************************/
15 /* FUNCTIONS ********************************************************/
17 CTextEditWindow::CTextEditWindow() : m_hFont(NULL
), m_hFontZoomed(NULL
), m_nAppIsMovingOrSizing(0)
23 #define X1 ((rc.left + rc.right - CXY_GRIP) / 2)
24 #define X2 (rc.right - CXY_GRIP)
26 #define Y1 ((rc.top + rc.bottom - CXY_GRIP) / 2)
27 #define Y2 (rc.bottom - CXY_GRIP)
28 #define RECT0 X0, Y0, X0 + CXY_GRIP, Y0 + CXY_GRIP // Upper Left
29 #define RECT1 X1, Y0, X1 + CXY_GRIP, Y0 + CXY_GRIP // Top
30 #define RECT2 X2, Y0, X2 + CXY_GRIP, Y0 + CXY_GRIP // Upper Right
31 #define RECT3 X0, Y1, X0 + CXY_GRIP, Y1 + CXY_GRIP // Left
32 #define RECT4 X2, Y1, X2 + CXY_GRIP, Y1 + CXY_GRIP // Right
33 #define RECT5 X0, Y2, X0 + CXY_GRIP, Y2 + CXY_GRIP // Lower Left
34 #define RECT6 X1, Y2, X1 + CXY_GRIP, Y2 + CXY_GRIP // Bottom
35 #define RECT7 X2, Y2, X2 + CXY_GRIP, Y2 + CXY_GRIP // Lower Right
37 INT
CTextEditWindow::DoHitTest(RECT
& rc
, POINT pt
)
41 SetRect(&rcGrip
, RECT0
);
42 if (PtInRect(&rcGrip
, pt
))
44 SetRect(&rcGrip
, RECT1
);
45 if (PtInRect(&rcGrip
, pt
))
47 SetRect(&rcGrip
, RECT2
);
48 if (PtInRect(&rcGrip
, pt
))
51 SetRect(&rcGrip
, RECT3
);
52 if (PtInRect(&rcGrip
, pt
))
54 SetRect(&rcGrip
, RECT4
);
55 if (PtInRect(&rcGrip
, pt
))
58 SetRect(&rcGrip
, RECT5
);
59 if (PtInRect(&rcGrip
, pt
))
61 SetRect(&rcGrip
, RECT6
);
62 if (PtInRect(&rcGrip
, pt
))
64 SetRect(&rcGrip
, RECT7
);
65 if (PtInRect(&rcGrip
, pt
))
70 InflateRect(&rcInner
, -3, -3);
71 if (!PtInRect(&rcInner
, pt
) && PtInRect(&rc
, pt
))
77 void CTextEditWindow::DrawGrip(HDC hDC
, RECT
& rc
)
79 HGDIOBJ hbrOld
= SelectObject(hDC
, GetStockObject(NULL_BRUSH
));
80 HPEN hPen
= CreatePen(PS_DOT
, 1, GetSysColor(COLOR_HIGHLIGHT
));
81 HGDIOBJ hPenOld
= SelectObject(hDC
, hPen
);
82 InflateRect(&rc
, -1, -1);
83 Rectangle(hDC
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
84 InflateRect(&rc
, 1, 1);
85 SelectObject(hDC
, hPenOld
);
86 SelectObject(hDC
, hbrOld
);
90 HBRUSH hbrHighlight
= GetSysColorBrush(COLOR_HIGHLIGHT
);
92 SetRect(&rcGrip
, RECT0
);
93 FillRect(hDC
, &rcGrip
, hbrHighlight
);
94 SetRect(&rcGrip
, RECT1
);
95 FillRect(hDC
, &rcGrip
, hbrHighlight
);
96 SetRect(&rcGrip
, RECT2
);
97 FillRect(hDC
, &rcGrip
, hbrHighlight
);
99 SetRect(&rcGrip
, RECT3
);
100 FillRect(hDC
, &rcGrip
, hbrHighlight
);
101 SetRect(&rcGrip
, RECT4
);
102 FillRect(hDC
, &rcGrip
, hbrHighlight
);
104 SetRect(&rcGrip
, RECT5
);
105 FillRect(hDC
, &rcGrip
, hbrHighlight
);
106 SetRect(&rcGrip
, RECT6
);
107 FillRect(hDC
, &rcGrip
, hbrHighlight
);
108 SetRect(&rcGrip
, RECT7
);
109 FillRect(hDC
, &rcGrip
, hbrHighlight
);
112 void CTextEditWindow::FixEditPos(LPCTSTR pszOldText
)
115 GetWindowText(szText
);
118 ::GetWindowRect(m_hwndParent
, &rcParent
);
120 RECT rc
, rcWnd
, rcText
;
121 GetWindowRect(&rcWnd
);
127 SelectObject(hDC
, m_hFontZoomed
);
129 GetTextMetrics(hDC
, &tm
);
130 szText
+= TEXT("x"); // This is a trick to enable the last newlines
131 const UINT uFormat
= DT_LEFT
| DT_TOP
| DT_EDITCONTROL
| DT_NOPREFIX
| DT_NOCLIP
|
132 DT_EXPANDTABS
| DT_WORDBREAK
;
133 DrawText(hDC
, szText
, -1, &rcText
, uFormat
| DT_CALCRECT
);
134 if (tm
.tmDescent
> 0)
135 rcText
.bottom
+= tm
.tmDescent
;
139 UnionRect(&rc
, &rcText
, &rcWnd
);
140 ::MapWindowPoints(NULL
, m_hwndParent
, (LPPOINT
)&rc
, 2);
143 ::GetClientRect(m_hwndParent
, &rcParent
);
144 IntersectRect(&rc
, &rcParent
, &rcWnd
);
146 ++m_nAppIsMovingOrSizing
;
147 MoveWindow(rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, FALSE
);
148 --m_nAppIsMovingOrSizing
;
150 DefWindowProc(WM_HSCROLL
, SB_LEFT
, 0);
151 DefWindowProc(WM_VSCROLL
, SB_TOP
, 0);
153 ::InvalidateRect(m_hwndParent
, &rc
, TRUE
);
156 LRESULT
CTextEditWindow::OnChar(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
158 if (wParam
== VK_TAB
)
159 return 0; // FIXME: Tabs
162 GetWindowText(szText
);
164 LRESULT ret
= DefWindowProc(nMsg
, wParam
, lParam
);
170 LRESULT
CTextEditWindow::OnKeyDown(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
172 if (wParam
== VK_ESCAPE
)
174 toolsModel
.OnCancelDraw();
179 GetWindowText(szText
);
181 LRESULT ret
= DefWindowProc(nMsg
, wParam
, lParam
);
186 LRESULT
CTextEditWindow::OnLButtonDown(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
188 LRESULT ret
= DefWindowProc(nMsg
, wParam
, lParam
);
189 DefWindowProc(WM_HSCROLL
, SB_LEFT
, 0);
190 DefWindowProc(WM_VSCROLL
, SB_TOP
, 0);
194 LRESULT
CTextEditWindow::OnEraseBkGnd(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
196 HDC hDC
= (HDC
)wParam
;
197 if (!toolsModel
.IsBackgroundTransparent())
201 HBRUSH hbr
= CreateSolidBrush(paletteModel
.GetBgColor());
202 FillRect(hDC
, &rc
, hbr
);
205 SetTextColor(hDC
, paletteModel
.GetFgColor());
209 LRESULT
CTextEditWindow::OnPaint(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
214 DefWindowProc(nMsg
, wParam
, lParam
);
226 LRESULT
CTextEditWindow::OnNCPaint(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
231 HDC hDC
= GetDCEx(NULL
, DCX_WINDOW
| DCX_PARENTCLIP
);
234 OffsetRect(&rc
, -rc
.left
, -rc
.top
);
242 LRESULT
CTextEditWindow::OnNCCalcSize(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
244 return 0; // No frame.
247 LRESULT
CTextEditWindow::OnNCHitTest(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
249 POINT pt
= { GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
) };
252 return DoHitTest(rc
, pt
);
255 LRESULT
CTextEditWindow::OnSetCursor(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
257 UINT nHitTest
= LOWORD(lParam
);
258 if (nHitTest
== HTCAPTION
)
260 SetCursor(LoadCursor(NULL
, IDC_SIZEALL
));
263 return DefWindowProc(nMsg
, wParam
, lParam
);
266 LRESULT
CTextEditWindow::OnMove(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
268 LRESULT ret
= DefWindowProc(nMsg
, wParam
, lParam
);
270 if (m_nAppIsMovingOrSizing
== 0)
273 InvalidateEditRect();
278 LRESULT
CTextEditWindow::OnSize(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
280 LRESULT ret
= DefWindowProc(nMsg
, wParam
, lParam
);
284 SendMessage(EM_SETRECTNP
, 0, (LPARAM
)&rc
);
285 SendMessage(EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(0, 0));
287 if (m_nAppIsMovingOrSizing
== 0)
290 InvalidateEditRect();
296 // Hack: Use DECLARE_WND_SUPERCLASS instead!
297 HWND
CTextEditWindow::Create(HWND hwndParent
)
299 m_hwndParent
= hwndParent
;
301 const DWORD style
= ES_LEFT
| ES_MULTILINE
| ES_WANTRETURN
| ES_AUTOVSCROLL
|
302 WS_CHILD
| WS_THICKFRAME
;
303 HWND hwnd
= ::CreateWindowEx(0, WC_EDIT
, NULL
, style
, 0, 0, 0, 0,
304 hwndParent
, NULL
, hProgInstance
, NULL
);
307 #undef SubclassWindow // Don't use this macro
308 SubclassWindow(hwnd
);
312 PostMessage(WM_SIZE
, 0, 0);
318 void CTextEditWindow::DoFillBack(HWND hwnd
, HDC hDC
)
320 if (toolsModel
.IsBackgroundTransparent())
324 SendMessage(EM_GETRECT
, 0, (LPARAM
)&rc
);
325 MapWindowPoints(hwnd
, (LPPOINT
)&rc
, 2);
327 HBRUSH hbr
= CreateSolidBrush(paletteModel
.GetBgColor());
328 FillRect(hDC
, &rc
, hbr
);
332 LRESULT
CTextEditWindow::OnCreate(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
338 LRESULT
CTextEditWindow::OnClose(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
343 DeleteObject(m_hFont
);
348 DeleteObject(m_hFontZoomed
);
349 m_hFontZoomed
= NULL
;
354 void CTextEditWindow::InvalidateEditRect()
358 ::MapWindowPoints(NULL
, m_hwndParent
, (LPPOINT
)&rc
, 2);
359 ::InvalidateRect(m_hwndParent
, &rc
, TRUE
);
362 MapWindowPoints(imageArea
, (LPPOINT
)&rc
, 2);
363 rc
.left
= UnZoomed(rc
.left
);
364 rc
.top
= UnZoomed(rc
.top
);
365 rc
.right
= UnZoomed(rc
.right
);
366 rc
.bottom
= UnZoomed(rc
.bottom
);
370 LRESULT
CTextEditWindow::OnPaletteModelColorChanged(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
376 LRESULT
CTextEditWindow::OnToolsModelSettingsChanged(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
382 LRESULT
CTextEditWindow::OnToolsModelZoomChanged(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
385 ValidateEditRect(NULL
);
389 LRESULT
CTextEditWindow::OnToolsModelToolChanged(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
391 if (wParam
== TOOL_TEXT
)
402 void CTextEditWindow::UpdateFont()
406 DeleteObject(m_hFont
);
411 DeleteObject(m_hFontZoomed
);
412 m_hFontZoomed
= NULL
;
416 ZeroMemory(&lf
, sizeof(lf
));
417 lf
.lfCharSet
= DEFAULT_CHARSET
; // registrySettings.CharSet; // Ignore
418 lf
.lfWeight
= (registrySettings
.Bold
? FW_BOLD
: FW_NORMAL
);
419 lf
.lfItalic
= registrySettings
.Italic
;
420 lf
.lfUnderline
= registrySettings
.Underline
;
421 lstrcpyn(lf
.lfFaceName
, registrySettings
.strFontName
, _countof(lf
.lfFaceName
));
426 INT nFontSize
= registrySettings
.PointSize
;
427 lf
.lfHeight
= -MulDiv(nFontSize
, GetDeviceCaps(hdc
, LOGPIXELSY
), 72);
431 m_hFont
= ::CreateFontIndirect(&lf
);
433 lf
.lfHeight
= Zoomed(lf
.lfHeight
);
434 m_hFontZoomed
= ::CreateFontIndirect(&lf
);
436 SetWindowFont(m_hWnd
, m_hFontZoomed
, TRUE
);
437 DefWindowProc(EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(0, 0));
444 LRESULT
CTextEditWindow::OnSetSel(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
446 LRESULT ret
= DefWindowProc(nMsg
, wParam
, lParam
);
447 DefWindowProc(WM_HSCROLL
, SB_LEFT
, 0);
448 DefWindowProc(WM_VSCROLL
, SB_TOP
, 0);
449 InvalidateEditRect();
453 BOOL
CTextEditWindow::GetEditRect(LPRECT prc
) const
459 void CTextEditWindow::ValidateEditRect(LPCRECT prc OPTIONAL
)
463 INT x0
= Zoomed(m_rc
.left
), y0
= Zoomed(m_rc
.top
);
464 INT x1
= Zoomed(m_rc
.right
), y1
= Zoomed(m_rc
.bottom
);
466 ++m_nAppIsMovingOrSizing
;
467 MoveWindow(x0
, y0
, x1
- x0
, y1
- y0
, TRUE
);
468 --m_nAppIsMovingOrSizing
;
471 void CTextEditWindow::Reposition()
476 ::MapWindowPoints(NULL
, imageArea
, (LPPOINT
)&rc
, 2);
477 imageArea
.GetClientRect(&rcImage
);
479 if (rc
.bottom
> rcImage
.bottom
)
481 rc
.top
= rcImage
.bottom
- (rc
.bottom
- rc
.top
);
482 rc
.bottom
= rcImage
.bottom
;
485 if (rc
.right
> rcImage
.right
)
487 rc
.left
= rcImage
.right
- (rc
.right
- rc
.left
);
488 rc
.right
= rcImage
.right
;
493 rc
.right
+= -rc
.left
;
499 rc
.bottom
+= -rc
.top
;
503 ++m_nAppIsMovingOrSizing
;
504 MoveWindow(rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, TRUE
);
505 --m_nAppIsMovingOrSizing
;
508 LRESULT
CTextEditWindow::OnMouseWheel(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
510 return ::SendMessage(GetParent(), nMsg
, wParam
, lParam
);