1 /*
2 * PROJECT: ReactOS Console Configuration DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/cpl/console/layout.c
5 * PURPOSE: Layout dialog
6 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8 */
9
10 #include "console.h"
11
12 #define NDEBUG
13 #include <debug.h>
14
15 /* CONSOLE WINDOW PREVIEW Control *********************************************/
16
17 #define WIN_PREVIEW_CLASS L"WinPreview"
18
19 typedef struct _WINPREV_DATA
20 {
21 HWND hWnd; // The window which this structure refers to
22 RECT rcMaxArea; // Maximum rectangle in which the preview window can be sized
23 SIZE siPreview; // Actual size of the preview window
24 SIZE siVirtScr; // Width and Height of the virtual screen
25 PVOID pData; // Private data
26 } WINPREV_DATA, *PWINPREV_DATA;
27
28 static LRESULT CALLBACK
29 WinPrevProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
30
31 BOOL
RegisterWinPrevClass(IN HINSTANCE hInstance)32 RegisterWinPrevClass(
33 IN HINSTANCE hInstance)
34 {
35 WNDCLASSW WndClass;
36
37 WndClass.lpszClassName = WIN_PREVIEW_CLASS;
38 WndClass.lpfnWndProc = WinPrevProc;
39 WndClass.style = 0;
40 WndClass.hInstance = hInstance;
41 WndClass.hIcon = NULL;
42 WndClass.hCursor = LoadCursorW(NULL, IDC_ARROW);
43 WndClass.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
44 WndClass.lpszMenuName = NULL;
45 WndClass.cbClsExtra = 0;
46 WndClass.cbWndExtra = 0; // sizeof(PWINPREV_DATA);
47
48 return (RegisterClassW(&WndClass) != 0);
49 }
50
51 BOOL
UnRegisterWinPrevClass(IN HINSTANCE hInstance)52 UnRegisterWinPrevClass(
53 IN HINSTANCE hInstance)
54 {
55 return UnregisterClassW(WIN_PREVIEW_CLASS, hInstance);
56 }
57
58 static VOID
WinPrev_OnDisplayChange(IN PWINPREV_DATA pData)59 WinPrev_OnDisplayChange(
60 IN PWINPREV_DATA pData)
61 {
62 // RECT rcNew;
63
64 pData->siVirtScr.cx = GetSystemMetrics(SM_CXVIRTUALSCREEN);
65 pData->siVirtScr.cy = GetSystemMetrics(SM_CYVIRTUALSCREEN);
66
67 /*
68 * The rescaling factor "siPreview / siVirtScr" should be the minimum of the ratios
69 * pData->rcMaxArea.right / pData->siVirtScr.cx , and
70 * pData->rcMaxArea.bottom / pData->siVirtScr.cy ,
71 * or equivalently, the maximum of the inverse of these ratios.
72 * This condition is equivalent to the following inequality being tested.
73 */
74 // if (pData->siVirtScr.cx / pData->rcMaxArea.right >= pData->siVirtScr.cy / pData->rcMaxArea.bottom)
75 if (pData->siVirtScr.cx * pData->rcMaxArea.bottom >= pData->siVirtScr.cy * pData->rcMaxArea.right)
76 {
77 pData->siPreview.cx = MulDiv(pData->siVirtScr.cx, pData->rcMaxArea.right, pData->siVirtScr.cx);
78 pData->siPreview.cy = MulDiv(pData->siVirtScr.cy, pData->rcMaxArea.right, pData->siVirtScr.cx);
79 }
80 else
81 {
82 pData->siPreview.cx = MulDiv(pData->siVirtScr.cx, pData->rcMaxArea.bottom, pData->siVirtScr.cy);
83 pData->siPreview.cy = MulDiv(pData->siVirtScr.cy, pData->rcMaxArea.bottom, pData->siVirtScr.cy);
84 }
85
86 /*
87 * Now, the lengths in screen-units can be rescaled into preview-units with:
88 * MulDiv(cx, pData->siPreview.cx, pData->siVirtScr.cx);
89 * and:
90 * MulDiv(cy, pData->siPreview.cy, pData->siVirtScr.cy);
91 */
92
93 #if 0 // TODO: Investigate!
94 /*
95 * Since both rcMaxArea and siPreview are client window area sizes,
96 * transform them into window sizes.
97 */
98 SetRect(&rcNew, 0, 0, pData->siPreview.cx, pData->siPreview.cy);
99 AdjustWindowRect(&rcNew,
100 WS_BORDER,
101 // GetWindowLongPtrW(pData->hWnd, GWL_STYLE) & ~WS_OVERLAPPED,
102 FALSE);
103 OffsetRect(&rcNew, -rcNew.left, -rcNew.top);
104 rcNew.right += 2;
105 rcNew.bottom += 2;
106 #endif
107
108 SetWindowPos(pData->hWnd,
109 0 /* HWND_TOP */,
110 0, 0,
111 pData->siPreview.cx, pData->siPreview.cy,
112 // rcNew.right, rcNew.bottom,
113 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
114 }
115
116 #define RescaleCX(pData, len) \
117 MulDiv((len), (pData)->siPreview.cx, (pData)->siVirtScr.cx)
118
119 #define RescaleCY(pData, len) \
120 MulDiv((len), (pData)->siPreview.cy, (pData)->siVirtScr.cy)
121
122 #define RescaleRect(pData, rect) \
123 do { \
124 (rect).left = RescaleCX((pData), (rect).left); \
125 (rect).right = RescaleCX((pData), (rect).right); \
126 (rect).top = RescaleCY((pData), (rect).top); \
127 (rect).bottom = RescaleCY((pData), (rect).bottom); \
128 } while (0)
129
130 #if 0
131 static VOID
132 WinPrev_OnSize(VOID)
133 {
134 }
135 #endif
136
137 static VOID
WinPrev_OnDraw(IN HDC hDC,IN PWINPREV_DATA pData)138 WinPrev_OnDraw(
139 IN HDC hDC,
140 IN PWINPREV_DATA pData)
141 {
142 PCONSOLE_STATE_INFO pConInfo = (PCONSOLE_STATE_INFO)pData->pData;
143 HBRUSH hBrush;
144 RECT rcWin, fRect;
145 SIZE /*siBorder,*/ siFrame, siButton, siScroll;
146 SIZE resize;
147
148 RECT rcItem;
149
150 GetClientRect(pData->hWnd, &rcItem);
151
152 /*
153 * Retrieve some system metrics and rescale them.
154 * They will be added separately, so that to always round the sizes up.
155 */
156
157 /* Don't care about border as it is almost always 1 and <= frame size */
158 /* Example: Frame = 4, or 13 ... while Border = 1 */
159 // siBorder.cx = GetSystemMetrics(SM_CXBORDER);
160 // siBorder.cy = GetSystemMetrics(SM_CYBORDER);
161
162 /* Window frame size */
163 siFrame.cx = GetSystemMetrics(SM_CXFRAME);
164 if (siFrame.cx > 0)
165 {
166 siFrame.cx = RescaleCX(pData, siFrame.cx);
167 siFrame.cx = max(1, siFrame.cx);
168 }
169 siFrame.cy = GetSystemMetrics(SM_CYFRAME);
170 if (siFrame.cy > 0)
171 {
172 siFrame.cy = RescaleCY(pData, siFrame.cy);
173 siFrame.cy = max(1, siFrame.cy);
174 }
175
176 /* Window caption buttons */
177 siButton.cx = GetSystemMetrics(SM_CXSIZE);
178 siButton.cx = RescaleCX(pData, siButton.cx);
179 siButton.cx = max(1, siButton.cx);
180
181 siButton.cy = GetSystemMetrics(SM_CYSIZE);
182 siButton.cy = RescaleCY(pData, siButton.cy);
183 siButton.cy = max(1, siButton.cy);
184
185 /* Enlarge them for improving their appearance */
186 // siButton.cx *= 2;
187 siButton.cy *= 2;
188
189 /* Dimensions of the scrollbars */
190 siScroll.cx = GetSystemMetrics(SM_CXVSCROLL);
191 siScroll.cx = RescaleCX(pData, siScroll.cx);
192 siScroll.cx = max(1, siScroll.cx);
193
194 siScroll.cy = GetSystemMetrics(SM_CYHSCROLL);
195 siScroll.cy = RescaleCY(pData, siScroll.cy);
196 siScroll.cy = max(1, siScroll.cy);
197
198
199 // FIXME: Use SM_CXMIN, SM_CYMIN ??
200
201
202 /*
203 * Compute the console window layout
204 */
205
206 if (FontPreview.hFont == NULL)
207 RefreshFontPreview(&FontPreview, pConInfo);
208
209 /* We start with the console client area, rescaled for the preview */
210 SetRect(&rcWin, 0, 0,
211 pConInfo->WindowSize.X * FontPreview.CharWidth,
212 pConInfo->WindowSize.Y * FontPreview.CharHeight);
213 RescaleRect(pData, rcWin);
214
215 /* Add the scrollbars if needed (does not account for any frame) */
216 if (pConInfo->WindowSize.X < pConInfo->ScreenBufferSize.X)
217 {
218 /* Horizontal scrollbar */
219 rcWin.bottom += siScroll.cy;
220 // NOTE: If an additional exterior frame is needed, add +1
221 }
222 else
223 {
224 /* No scrollbar */
225 siScroll.cy = 0;
226 }
227 if (pConInfo->WindowSize.Y < pConInfo->ScreenBufferSize.Y)
228 {
229 /* Vertical scrollbar */
230 rcWin.right += siScroll.cx;
231 // NOTE: If an additional exterior frame is needed, add +1
232 }
233 else
234 {
235 /* No scrollbar */
236 siScroll.cx = 0;
237 }
238
239 /* Add the title bar, taking into account the frames */
240 rcWin.top -= siButton.cy - 1;
241
242 /* If we have a non-zero window frame size, add an interior border and the frame */
243 resize.cx = (siFrame.cx > 0 ? 1 + siFrame.cx : 0);
244 resize.cy = (siFrame.cy > 0 ? 1 + siFrame.cy : 0);
245
246 /* Add the outer border */
247 ++resize.cx, ++resize.cy;
248
249 InflateRect(&rcWin, resize.cx, resize.cy);
250
251 /* Finally, move the window rectangle back to its correct origin */
252 OffsetRect(&rcWin, -rcWin.left, -rcWin.top);
253
254 if ( pConInfo->WindowPosition.x == MAXDWORD &&
255 pConInfo->WindowPosition.y == MAXDWORD )
256 {
257 // OffsetRect(&rcWin, (rcItem.right - rcItem.left) / 3, (rcItem.bottom - rcItem.top) / 3);
258 OffsetRect(&rcWin, 0, 0);
259 }
260 else
261 {
262 OffsetRect(&rcWin,
263 RescaleCX(pData, pConInfo->WindowPosition.x),
264 RescaleCY(pData, pConInfo->WindowPosition.y));
265 }
266
267
268 /*
269 * Paint the preview window
270 */
271
272 /* Fill the background with desktop colour */
273 FillRect(hDC, &rcItem, GetSysColorBrush(COLOR_BACKGROUND));
274
275 /*
276 * Draw the exterior frame. Use 'FillRect' instead of 'FrameRect'
277 * so that, when we want to draw frames around other elements,
278 * we can just instead separate them with space instead of redrawing
279 * a frame with 'FrameRect'.
280 */
281 FillRect(hDC, &rcWin, GetSysColorBrush(COLOR_WINDOWFRAME));
282 InflateRect(&rcWin, -1, -1);
283
284 /* Draw the border */
285 hBrush = GetSysColorBrush(COLOR_ACTIVEBORDER);
286 if (siFrame.cx > 0)
287 {
288 SetRect(&fRect, rcWin.left, rcWin.top, rcWin.left + siFrame.cx, rcWin.bottom);
289 FillRect(hDC, &fRect, hBrush);
290 SetRect(&fRect, rcWin.right - siFrame.cx, rcWin.top, rcWin.right, rcWin.bottom);
291 FillRect(hDC, &fRect, hBrush);
292
293 InflateRect(&rcWin, -siFrame.cx, 0);
294 }
295 if (siFrame.cy > 0)
296 {
297 SetRect(&fRect, rcWin.left, rcWin.top, rcWin.right, rcWin.top + siFrame.cy);
298 FillRect(hDC, &fRect, hBrush);
299 SetRect(&fRect, rcWin.left, rcWin.bottom - siFrame.cy, rcWin.right, rcWin.bottom);
300 FillRect(hDC, &fRect, hBrush);
301
302 InflateRect(&rcWin, 0, -siFrame.cy);
303 }
304
305 /* Draw the interior frame if we had a border */
306 if (siFrame.cx > 0 || siFrame.cy > 0)
307 {
308 #if 0 // See the remark above
309 SetRect(&fRect, rcWin.left, rcWin.top, rcWin.right, rcWin.bottom);
310 FrameRect(hDC, &fRect, GetSysColorBrush(COLOR_WINDOWFRAME));
311 #endif
312 InflateRect(&rcWin, (siFrame.cx > 0 ? -1 : 0), (siFrame.cy > 0 ? -1 : 0));
313 }
314
315 /* Draw the console window title bar */
316 hBrush = GetSysColorBrush(COLOR_BTNFACE);
317
318 /* Draw the system menu (left button) */
319 SetRect(&fRect, rcWin.left, rcWin.top, rcWin.left + siButton.cx, rcWin.top + siButton.cy - 2);
320 // DrawFrameControl(hDC, &fRect, DFC_CAPTION, DFCS_CAPTIONCLOSE);
321 FillRect(hDC, &fRect, hBrush);
322 fRect.right++; // Separation
323
324 /* Draw the caption bar */
325 SetRect(&fRect, fRect.right, fRect.top, rcWin.right - 2 * (siButton.cx + 1), fRect.bottom);
326 FillRect(hDC, &fRect, GetSysColorBrush(COLOR_ACTIVECAPTION));
327 fRect.right++; // Separation
328
329 /* Draw the minimize menu (first right button) */
330 SetRect(&fRect, fRect.right, fRect.top, fRect.right + siButton.cx, fRect.bottom);
331 // DrawFrameControl(hDC, &fRect, DFC_CAPTION, DFCS_CAPTIONMIN);
332 FillRect(hDC, &fRect, hBrush);
333 fRect.right++; // Separation
334
335 /* Draw the maximize menu (second right button) */
336 SetRect(&fRect, fRect.right, fRect.top, fRect.right + siButton.cx, fRect.bottom);
337 // DrawFrameControl(hDC, &fRect, DFC_CAPTION, DFCS_CAPTIONMAX);
338 FillRect(hDC, &fRect, hBrush);
339
340 rcWin.top += siButton.cy - 1;
341
342 /* Add the scrollbars if needed */
343 if (siScroll.cy > 0 || siScroll.cx > 0)
344 {
345 LONG right, bottom;
346
347 right = rcWin.right;
348 bottom = rcWin.bottom;
349
350 /*
351 * If both the horizontal and vertical scrollbars are present,
352 * reserve some space for the "dead square" at the bottom right.
353 */
354 if (siScroll.cy > 0 && siScroll.cx > 0)
355 {
356 right -= (1 + siScroll.cx);
357 bottom -= (1 + siScroll.cy);
358 }
359
360 hBrush = GetSysColorBrush(COLOR_SCROLLBAR);
361
362 /* Horizontal scrollbar */
363 if (siScroll.cy > 0)
364 {
365 SetRect(&fRect, rcWin.left, rcWin.bottom - siScroll.cy, right, rcWin.bottom);
366 FillRect(hDC, &fRect, hBrush);
367 }
368
369 /* Vertical scrollbar */
370 if (siScroll.cx > 0)
371 {
372 SetRect(&fRect, rcWin.right - siScroll.cx, rcWin.top, rcWin.right, bottom);
373 FillRect(hDC, &fRect, hBrush);
374 }
375
376 /*
377 * If both the horizontal and vertical scrollbars are present,
378 * draw the "dead square" at the bottom right.
379 */
380 if (siScroll.cy > 0 && siScroll.cx > 0)
381 {
382 SetRect(&fRect, rcWin.right - siScroll.cx, rcWin.bottom - siScroll.cy, rcWin.right, rcWin.bottom);
383 FillRect(hDC, &fRect, hBrush);
384 }
385
386 // NOTE: If an additional exterior frame is needed, remove +1 for each direction
387 rcWin.right -= siScroll.cx;
388 rcWin.bottom -= siScroll.cy;
389 }
390
391 /* Draw the console background */
392 hBrush = CreateSolidBrush(pConInfo->ColorTable[BkgdAttribFromAttrib(pConInfo->ScreenAttributes)]);
393 FillRect(hDC, &rcWin, hBrush ? hBrush : GetStockObject(BLACK_BRUSH));
394 if (hBrush) DeleteObject(hBrush);
395 }
396
397 static LRESULT CALLBACK
WinPrevProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)398 WinPrevProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
399 {
400 PWINPREV_DATA pData;
401
402 pData = (PWINPREV_DATA)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
403
404 switch (msg)
405 {
406 case WM_CREATE:
407 {
408 pData = (PWINPREV_DATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pData));
409 if (!pData)
410 {
411 /* We failed to allocate our private data, halt the window creation */
412 return (LRESULT)-1;
413 }
414 pData->hWnd = hWnd;
415 pData->pData = ConInfo;
416 GetClientRect(pData->hWnd, &pData->rcMaxArea);
417 // LPCREATESTRUCT::cx and cy give window (not client) size
418 WinPrev_OnDisplayChange(pData);
419 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)pData);
420 break;
421 }
422
423 case WM_DESTROY:
424 {
425 if (pData)
426 HeapFree(GetProcessHeap(), 0, pData);
427 break;
428 }
429
430 case WM_DISPLAYCHANGE:
431 {
432 WinPrev_OnDisplayChange(pData);
433 UpdateWindow(hWnd);
434 // InvalidateRect(hWnd, NULL, FALSE);
435 break;
436 }
437
438 case WM_SIZE:
439 break;
440
441 case WM_ERASEBKGND:
442 return 1;
443
444 case WM_PAINT:
445 {
446 PAINTSTRUCT ps;
447 BeginPaint(hWnd, &ps);
448 WinPrev_OnDraw(ps.hdc, pData);
449 EndPaint(hWnd, &ps);
450 return 0;
451 }
452 }
453
454 return DefWindowProcW(hWnd, msg, wParam, lParam);
455 }
456
457
458 /* CONSOLE TEXT PREVIEW *******************************************************/
459
460 const WCHAR szPreviewText[] =
461 L"C:\\ReactOS>dir\n" \
462 L"SYSTEM <DIR> 13-04-15 5:00a\n" \
463 L"SYSTEM32 <DIR> 13-04-15 5:00a\n" \
464 L"readme txt 1739 13-04-15 5:00a\n" \
465 L"explorer exe 3329536 13-04-15 5:00a\n" \
466 L"vgafonts cab 18736 13-04-15 5:00a\n" \
467 L"setuplog txt 313 13-04-15 5:00a\n" \
468 L"win ini 7005 13-04-15 5:00a\n" ;
469
470 VOID
PaintText(IN LPDRAWITEMSTRUCT drawItem,IN PCONSOLE_STATE_INFO pConInfo,IN TEXT_TYPE TextMode)471 PaintText(
472 IN LPDRAWITEMSTRUCT drawItem,
473 IN PCONSOLE_STATE_INFO pConInfo,
474 IN TEXT_TYPE TextMode)
475 {
476 USHORT CurrentAttrib;
477 COLORREF pbkColor, ptColor;
478 COLORREF nbkColor, ntColor;
479 HBRUSH hBrush;
480 HFONT hOldFont;
481
482 if (TextMode == Screen)
483 CurrentAttrib = pConInfo->ScreenAttributes;
484 else if (TextMode == Popup)
485 CurrentAttrib = pConInfo->PopupAttributes;
486 else
487 return;
488
489 nbkColor = pConInfo->ColorTable[BkgdAttribFromAttrib(CurrentAttrib)];
490 ntColor = pConInfo->ColorTable[TextAttribFromAttrib(CurrentAttrib)];
491
492 /* Draw the console background */
493 hBrush = CreateSolidBrush(nbkColor);
494 FillRect(drawItem->hDC, &drawItem->rcItem, hBrush ? hBrush : GetStockObject(BLACK_BRUSH));
495 if (hBrush) DeleteObject(hBrush);
496
497 /* Refresh the font preview, getting a new font if necessary */
498 if (FontPreview.hFont == NULL)
499 RefreshFontPreview(&FontPreview, pConInfo);
500 /* Recheck hFont since RefreshFontPreview() may not have updated it */
501 if (FontPreview.hFont == NULL)
502 return;
503
504 /* Draw the preview text using the current font */
505 hOldFont = SelectObject(drawItem->hDC, FontPreview.hFont);
506 // if (!hOldFont) return;
507
508 /* Add a few space between the preview window border and the text sample */
509 InflateRect(&drawItem->rcItem, -2, -2);
510
511 ptColor = SetTextColor(drawItem->hDC, ntColor);
512 pbkColor = SetBkColor(drawItem->hDC, nbkColor);
513 DrawTextW(drawItem->hDC, szPreviewText, (INT)wcslen(szPreviewText), &drawItem->rcItem, 0);
514 SetTextColor(drawItem->hDC, ptColor);
515 SetBkColor(drawItem->hDC, pbkColor);
516
517 SelectObject(drawItem->hDC, hOldFont);
518 }
519
520
521 /* LAYOUT DIALOG **************************************************************/
522
523 INT_PTR
524 CALLBACK
LayoutProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)525 LayoutProc(HWND hDlg,
526 UINT uMsg,
527 WPARAM wParam,
528 LPARAM lParam)
529 {
530 switch (uMsg)
531 {
532 case WM_INITDIALOG:
533 {
534 /* Multi-monitor support */
535 LONG xVirtScr, yVirtScr; // Coordinates of the top-left virtual screen
536 LONG cxVirtScr, cyVirtScr; // Width and Height of the virtual screen
537 LONG cxFrame , cyFrame ; // Thickness of the window frame
538
539 xVirtScr = GetSystemMetrics(SM_XVIRTUALSCREEN);
540 yVirtScr = GetSystemMetrics(SM_YVIRTUALSCREEN);
541 cxVirtScr = GetSystemMetrics(SM_CXVIRTUALSCREEN);
542 cyVirtScr = GetSystemMetrics(SM_CYVIRTUALSCREEN);
543 cxFrame = GetSystemMetrics(SM_CXFRAME);
544 cyFrame = GetSystemMetrics(SM_CYFRAME);
545
546 SendDlgItemMessageW(hDlg, IDC_UPDOWN_SCREEN_BUFFER_HEIGHT, UDM_SETRANGE, 0, (LPARAM)MAKELONG(9999, 1));
547 SendDlgItemMessageW(hDlg, IDC_UPDOWN_SCREEN_BUFFER_WIDTH , UDM_SETRANGE, 0, (LPARAM)MAKELONG(9999, 1));
548 SendDlgItemMessageW(hDlg, IDC_UPDOWN_WINDOW_SIZE_HEIGHT, UDM_SETRANGE, 0, (LPARAM)MAKELONG(9999, 1));
549 SendDlgItemMessageW(hDlg, IDC_UPDOWN_WINDOW_SIZE_WIDTH , UDM_SETRANGE, 0, (LPARAM)MAKELONG(9999, 1));
550
551 SetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, ConInfo->ScreenBufferSize.Y, FALSE);
552 SetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH , ConInfo->ScreenBufferSize.X, FALSE);
553 SetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT, ConInfo->WindowSize.Y, FALSE);
554 SetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_WIDTH , ConInfo->WindowSize.X, FALSE);
555
556 SendDlgItemMessageW(hDlg, IDC_UPDOWN_WINDOW_POS_LEFT, UDM_SETRANGE, 0,
557 (LPARAM)MAKELONG(xVirtScr + cxVirtScr - cxFrame, xVirtScr - cxFrame));
558 SendDlgItemMessageW(hDlg, IDC_UPDOWN_WINDOW_POS_TOP , UDM_SETRANGE, 0,
559 (LPARAM)MAKELONG(yVirtScr + cyVirtScr - cyFrame, yVirtScr - cyFrame));
560
561 SetDlgItemInt(hDlg, IDC_EDIT_WINDOW_POS_LEFT, ConInfo->WindowPosition.x, TRUE);
562 SetDlgItemInt(hDlg, IDC_EDIT_WINDOW_POS_TOP , ConInfo->WindowPosition.y, TRUE);
563
564 if (ConInfo->AutoPosition)
565 {
566 EnableDlgItem(hDlg, IDC_EDIT_WINDOW_POS_LEFT, FALSE);
567 EnableDlgItem(hDlg, IDC_EDIT_WINDOW_POS_TOP , FALSE);
568 EnableDlgItem(hDlg, IDC_UPDOWN_WINDOW_POS_LEFT, FALSE);
569 EnableDlgItem(hDlg, IDC_UPDOWN_WINDOW_POS_TOP , FALSE);
570 }
571 CheckDlgButton(hDlg, IDC_CHECK_SYSTEM_POS_WINDOW,
572 ConInfo->AutoPosition ? BST_CHECKED : BST_UNCHECKED);
573
574 return TRUE;
575 }
576
577 case WM_DISPLAYCHANGE:
578 {
579 /* Retransmit to the preview window */
580 SendDlgItemMessageW(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW,
581 WM_DISPLAYCHANGE, wParam, lParam);
582 break;
583 }
584
585 case WM_NOTIFY:
586 {
587 LPPSHNOTIFY lppsn = (LPPSHNOTIFY)lParam;
588
589 if (lppsn->hdr.code == UDN_DELTAPOS)
590 {
591 LPNMUPDOWN lpnmud = (LPNMUPDOWN)lParam;
592 DWORD wheight, wwidth;
593 DWORD sheight, swidth;
594 DWORD left, top;
595
596 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_SIZE_WIDTH)
597 {
598 wwidth = lpnmud->iPos + lpnmud->iDelta;
599 }
600 else
601 {
602 wwidth = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_WIDTH, NULL, FALSE);
603 }
604
605 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_SIZE_HEIGHT)
606 {
607 wheight = lpnmud->iPos + lpnmud->iDelta;
608 }
609 else
610 {
611 wheight = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT, NULL, FALSE);
612 }
613
614 if (lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_WIDTH)
615 {
616 swidth = lpnmud->iPos + lpnmud->iDelta;
617 }
618 else
619 {
620 swidth = GetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, NULL, FALSE);
621 }
622
623 if (lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_HEIGHT)
624 {
625 sheight = lpnmud->iPos + lpnmud->iDelta;
626 }
627 else
628 {
629 sheight = GetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, NULL, FALSE);
630 }
631
632 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_POS_LEFT)
633 {
634 left = lpnmud->iPos + lpnmud->iDelta;
635 }
636 else
637 {
638 left = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_POS_LEFT, NULL, TRUE);
639 }
640
641 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_POS_TOP)
642 {
643 top = lpnmud->iPos + lpnmud->iDelta;
644 }
645 else
646 {
647 top = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_POS_TOP, NULL, TRUE);
648 }
649
650 if (lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_SIZE_WIDTH || lppsn->hdr.idFrom == IDC_UPDOWN_WINDOW_SIZE_HEIGHT)
651 {
652 /* Automatically adjust screen buffer size when window size enlarges */
653 if (wwidth >= swidth)
654 {
655 SetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, wwidth, TRUE);
656 swidth = wwidth;
657 }
658 if (wheight >= sheight)
659 {
660 SetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, wheight, TRUE);
661 sheight = wheight;
662 }
663 }
664
665 /* Be sure that the (new) screen buffer sizes are in the correct range */
666 swidth = min(max(swidth , 1), 0xFFFF);
667 sheight = min(max(sheight, 1), 0xFFFF);
668
669 if (lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_WIDTH || lppsn->hdr.idFrom == IDC_UPDOWN_SCREEN_BUFFER_HEIGHT)
670 {
671 /* Automatically adjust window size when screen buffer decreases */
672 if (wwidth > swidth)
673 {
674 SetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_WIDTH, swidth, TRUE);
675 wwidth = swidth;
676 }
677 if (wheight > sheight)
678 {
679 SetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT, sheight, TRUE);
680 wheight = sheight;
681 }
682 }
683
684 ConInfo->ScreenBufferSize.X = (SHORT)swidth;
685 ConInfo->ScreenBufferSize.Y = (SHORT)sheight;
686 ConInfo->WindowSize.X = (SHORT)wwidth;
687 ConInfo->WindowSize.Y = (SHORT)wheight;
688 ConInfo->WindowPosition.x = left;
689 ConInfo->WindowPosition.y = top;
690
691 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW), NULL, TRUE);
692 PropSheet_Changed(GetParent(hDlg), hDlg);
693 }
694 break;
695 }
696
697 case WM_COMMAND:
698 {
699 if (HIWORD(wParam) == EN_KILLFOCUS)
700 {
701 switch (LOWORD(wParam))
702 {
703 case IDC_EDIT_SCREEN_BUFFER_WIDTH:
704 {
705 DWORD swidth, wwidth;
706
707 swidth = GetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, NULL, FALSE);
708 wwidth = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_WIDTH , NULL, FALSE);
709
710 /* Be sure that the (new) screen buffer width is in the correct range */
711 swidth = min(max(swidth, 1), 0xFFFF);
712
713 /* Automatically adjust window size when screen buffer decreases */
714 if (wwidth > swidth)
715 {
716 wwidth = swidth;
717 SetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_WIDTH, wwidth, TRUE);
718 }
719
720 ConInfo->ScreenBufferSize.X = (SHORT)swidth;
721 ConInfo->WindowSize.X = (SHORT)wwidth;
722
723 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW), NULL, TRUE);
724 PropSheet_Changed(GetParent(hDlg), hDlg);
725 break;
726 }
727
728 case IDC_EDIT_WINDOW_SIZE_WIDTH:
729 {
730 DWORD swidth, wwidth;
731
732 swidth = GetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, NULL, FALSE);
733 wwidth = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_WIDTH , NULL, FALSE);
734
735 /* Automatically adjust screen buffer size when window size enlarges */
736 if (wwidth >= swidth)
737 {
738 swidth = wwidth;
739
740 /* Be sure that the (new) screen buffer width is in the correct range */
741 swidth = min(max(swidth, 1), 0xFFFF);
742
743 SetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_WIDTH, swidth, TRUE);
744 }
745
746 ConInfo->ScreenBufferSize.X = (SHORT)swidth;
747 ConInfo->WindowSize.X = (SHORT)wwidth;
748
749 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW), NULL, TRUE);
750 PropSheet_Changed(GetParent(hDlg), hDlg);
751 break;
752 }
753
754 case IDC_EDIT_SCREEN_BUFFER_HEIGHT:
755 {
756 DWORD sheight, wheight;
757
758 sheight = GetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, NULL, FALSE);
759 wheight = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT , NULL, FALSE);
760
761 /* Be sure that the (new) screen buffer width is in the correct range */
762 sheight = min(max(sheight, 1), 0xFFFF);
763
764 /* Automatically adjust window size when screen buffer decreases */
765 if (wheight > sheight)
766 {
767 wheight = sheight;
768 SetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT, wheight, TRUE);
769 }
770
771 ConInfo->ScreenBufferSize.Y = (SHORT)sheight;
772 ConInfo->WindowSize.Y = (SHORT)wheight;
773
774 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW), NULL, TRUE);
775 PropSheet_Changed(GetParent(hDlg), hDlg);
776 break;
777 }
778
779 case IDC_EDIT_WINDOW_SIZE_HEIGHT:
780 {
781 DWORD sheight, wheight;
782
783 sheight = GetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, NULL, FALSE);
784 wheight = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_SIZE_HEIGHT , NULL, FALSE);
785
786 /* Automatically adjust screen buffer size when window size enlarges */
787 if (wheight >= sheight)
788 {
789 sheight = wheight;
790
791 /* Be sure that the (new) screen buffer width is in the correct range */
792 sheight = min(max(sheight, 1), 0xFFFF);
793
794 SetDlgItemInt(hDlg, IDC_EDIT_SCREEN_BUFFER_HEIGHT, sheight, TRUE);
795 }
796
797 ConInfo->ScreenBufferSize.Y = (SHORT)sheight;
798 ConInfo->WindowSize.Y = (SHORT)wheight;
799
800 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW), NULL, TRUE);
801 PropSheet_Changed(GetParent(hDlg), hDlg);
802 break;
803 }
804
805 case IDC_EDIT_WINDOW_POS_LEFT:
806 case IDC_EDIT_WINDOW_POS_TOP:
807 {
808 ConInfo->WindowPosition.x = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_POS_LEFT, NULL, TRUE);
809 ConInfo->WindowPosition.y = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_POS_TOP , NULL, TRUE);
810
811 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW), NULL, TRUE);
812 PropSheet_Changed(GetParent(hDlg), hDlg);
813 break;
814 }
815 }
816 }
817 else
818 if (HIWORD(wParam) == BN_CLICKED &&
819 LOWORD(wParam) == IDC_CHECK_SYSTEM_POS_WINDOW)
820 {
821 if (IsDlgButtonChecked(hDlg, IDC_CHECK_SYSTEM_POS_WINDOW) == BST_CHECKED)
822 {
823 EnableDlgItem(hDlg, IDC_EDIT_WINDOW_POS_LEFT, FALSE);
824 EnableDlgItem(hDlg, IDC_EDIT_WINDOW_POS_TOP , FALSE);
825 EnableDlgItem(hDlg, IDC_UPDOWN_WINDOW_POS_LEFT, FALSE);
826 EnableDlgItem(hDlg, IDC_UPDOWN_WINDOW_POS_TOP , FALSE);
827
828 ConInfo->AutoPosition = TRUE;
829 // Do not touch ConInfo->WindowPosition !!
830
831 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW), NULL, TRUE);
832 PropSheet_Changed(GetParent(hDlg), hDlg);
833 }
834 else
835 {
836 ULONG left, top;
837
838 left = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_POS_LEFT, NULL, TRUE);
839 top = GetDlgItemInt(hDlg, IDC_EDIT_WINDOW_POS_TOP , NULL, TRUE);
840
841 EnableDlgItem(hDlg, IDC_EDIT_WINDOW_POS_LEFT, TRUE);
842 EnableDlgItem(hDlg, IDC_EDIT_WINDOW_POS_TOP , TRUE);
843 EnableDlgItem(hDlg, IDC_UPDOWN_WINDOW_POS_LEFT, TRUE);
844 EnableDlgItem(hDlg, IDC_UPDOWN_WINDOW_POS_TOP , TRUE);
845
846 ConInfo->AutoPosition = FALSE;
847 ConInfo->WindowPosition.x = left;
848 ConInfo->WindowPosition.y = top;
849
850 InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_LAYOUT_WINDOW_PREVIEW), NULL, TRUE);
851 PropSheet_Changed(GetParent(hDlg), hDlg);
852 }
853 }
854
855 break;
856 }
857
858 default:
859 break;
860 }
861
862 return FALSE;
863 }
864