2 * PROJECT: ReactOS VGA Font Editor
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Implements the main window of the application
5 * COPYRIGHT: Copyright 2008 Colin Finck (colin@reactos.org)
10 static const WCHAR szMainWndClass
[] = L
"VGAFontEditMainWndClass";
13 InitResources(IN PMAIN_WND_INFO Info
)
21 hMemDC
= CreateCompatibleDC(NULL
);
22 hMainDC
= GetDC(Info
->hMainWnd
);
24 // Create the "Box" bitmap
25 Info
->hBoxBmp
= CreateCompatibleBitmap(hMainDC
, CHARACTER_BOX_WIDTH
, CHARACTER_BOX_HEIGHT
);
26 hBitmapOld
= SelectObject(hMemDC
, Info
->hBoxBmp
);
30 rect
.right
= CHARACTER_INFO_BOX_WIDTH
;
31 rect
.bottom
= CHARACTER_INFO_BOX_HEIGHT
;
32 FillRect( hMemDC
, &rect
, (HBRUSH
)(COLOR_BTNFACE
+ 1) );
34 hPenOld
= SelectObject( hMemDC
, GetStockObject(WHITE_PEN
) );
35 Rectangle(hMemDC
, 0, 0, CHARACTER_INFO_BOX_WIDTH
- 1, 2);
36 Rectangle(hMemDC
, 0, 2, 2, CHARACTER_INFO_BOX_HEIGHT
- 1);
37 hPen
= SelectObject(hMemDC
, hPenOld
);
39 hPen
= CreatePen( PS_SOLID
, 1, RGB(128, 128, 128) );
40 hPenOld
= SelectObject(hMemDC
, hPen
);
41 Rectangle(hMemDC
, 1, CHARACTER_INFO_BOX_HEIGHT
- 2, CHARACTER_INFO_BOX_WIDTH
, CHARACTER_INFO_BOX_HEIGHT
);
42 Rectangle(hMemDC
, CHARACTER_INFO_BOX_WIDTH
- 2, 1, CHARACTER_INFO_BOX_WIDTH
, CHARACTER_INFO_BOX_HEIGHT
- 2);
44 SetPixel( hMemDC
, CHARACTER_INFO_BOX_WIDTH
- 1, 0, RGB(128, 128, 128) );
45 SetPixel( hMemDC
, 0, CHARACTER_INFO_BOX_HEIGHT
- 1, RGB(128, 128, 128) );
46 SelectObject(hMemDC
, hBitmapOld
);
48 hPen
= SelectObject(hMemDC
, hPenOld
);
51 ReleaseDC(Info
->hMainWnd
, hMainDC
);
55 UnInitResources(IN PMAIN_WND_INFO Info
)
57 DeleteObject(Info
->hBoxBmp
);
61 AddToolbarButton(IN PMAIN_WND_INFO Info
, IN INT iBitmap
, IN INT idCommand
, IN UINT uID
)
66 if( AllocAndLoadString(&pszTooltip
, uID
) )
68 tbb
.fsState
= TBSTATE_ENABLED
;
69 tbb
.iBitmap
= iBitmap
;
70 tbb
.idCommand
= idCommand
;
71 tbb
.iString
= (INT_PTR
)pszTooltip
;
73 SendMessageW( Info
->hToolbar
, TB_ADDBUTTONSW
, 1, (LPARAM
)&tbb
);
74 HeapFree(hProcessHeap
, 0, pszTooltip
);
79 SetToolbarButtonState(IN PMAIN_WND_INFO Info
, INT idCommand
, BOOL bEnabled
)
81 TBBUTTONINFOW tbbi
= {0,};
83 tbbi
.cbSize
= sizeof(tbbi
);
84 tbbi
.dwMask
= TBIF_STATE
;
85 tbbi
.fsState
= (bEnabled
? TBSTATE_ENABLED
: 0);
87 SendMessageW(Info
->hToolbar
, TB_SETBUTTONINFOW
, idCommand
, (LPARAM
)&tbbi
);
91 SetToolbarFileButtonState(IN PMAIN_WND_INFO Info
, BOOL bEnabled
)
93 SetToolbarButtonState(Info
, ID_FILE_SAVE
, bEnabled
);
94 SetToolbarButtonState(Info
, ID_EDIT_GLYPH
, bEnabled
);
95 SetToolbarButtonState(Info
, ID_EDIT_COPY
, bEnabled
);
99 AddToolbarSeparator(IN PMAIN_WND_INFO Info
)
103 tbb
.fsStyle
= BTNS_SEP
;
105 SendMessageW( Info
->hToolbar
, TB_ADDBUTTONSW
, 1, (LPARAM
)&tbb
);
109 InitMainWnd(IN PMAIN_WND_INFO Info
)
111 CLIENTCREATESTRUCT ccs
;
113 INT iStandardBitmaps
;
117 Info
->hToolbar
= CreateWindowExW(0,
120 WS_VISIBLE
| WS_CHILD
| TBSTYLE_TOOLTIPS
,
130 // Identify the used Common Controls version
131 SendMessageW(Info
->hToolbar
, TB_BUTTONSTRUCTSIZE
, sizeof(TBBUTTON
), 0);
134 SendMessageW(Info
->hToolbar
, TB_SETMAXTEXTROWS
, 0, 0);
136 // Add the toolbar bitmaps
137 tbab
.hInst
= HINST_COMMCTRL
;
138 tbab
.nID
= IDB_STD_SMALL_COLOR
;
139 iStandardBitmaps
= (INT
)SendMessageW(Info
->hToolbar
, TB_ADDBITMAP
, 0, (LPARAM
)&tbab
);
141 tbab
.hInst
= hInstance
;
142 tbab
.nID
= IDB_MAIN_TOOLBAR
;
143 iCustomBitmaps
= (INT
)SendMessageW(Info
->hToolbar
, TB_ADDBITMAP
, 0, (LPARAM
)&tbab
);
145 // Add the toolbar buttons
146 AddToolbarButton(Info
, iStandardBitmaps
+ STD_FILENEW
, ID_FILE_NEW
, IDS_TOOLTIP_NEW
);
147 AddToolbarButton(Info
, iStandardBitmaps
+ STD_FILEOPEN
, ID_FILE_OPEN
, IDS_TOOLTIP_OPEN
);
148 AddToolbarButton(Info
, iStandardBitmaps
+ STD_FILESAVE
, ID_FILE_SAVE
, IDS_TOOLTIP_SAVE
);
149 AddToolbarSeparator(Info
);
150 AddToolbarButton(Info
, iCustomBitmaps
+ TOOLBAR_EDIT_GLYPH
, ID_EDIT_GLYPH
, IDS_TOOLTIP_EDIT_GLYPH
);
151 AddToolbarSeparator(Info
);
152 AddToolbarButton(Info
, iStandardBitmaps
+ STD_COPY
, ID_EDIT_COPY
, IDS_TOOLTIP_COPY
);
153 AddToolbarButton(Info
, iStandardBitmaps
+ STD_PASTE
, ID_EDIT_PASTE
, IDS_TOOLTIP_PASTE
);
155 SetToolbarFileButtonState(Info
, FALSE
);
156 SetPasteButtonState(Info
);
158 // Add the MDI client area
159 ccs
.hWindowMenu
= GetSubMenu(Info
->hMenu
, 2);
160 ccs
.idFirstChild
= ID_MDI_FIRSTCHILD
;
162 Info
->hMdiClient
= CreateWindowExW(WS_EX_CLIENTEDGE
,
165 WS_VISIBLE
| WS_CHILD
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
| WS_VSCROLL
| WS_HSCROLL
,
175 // Initialize the file handling
176 FileInitialize(Info
->hMainWnd
);
180 InitMenuPopup(IN PMAIN_WND_INFO Info
)
184 uState
= MF_BYCOMMAND
| !(Info
->CurrentFontWnd
);
186 EnableMenuItem(Info
->hMenu
, ID_FILE_CLOSE
, uState
);
187 EnableMenuItem(Info
->hMenu
, ID_FILE_SAVE
, uState
);
188 EnableMenuItem(Info
->hMenu
, ID_FILE_SAVE_AS
, uState
);
190 EnableMenuItem(Info
->hMenu
, ID_EDIT_COPY
, uState
);
191 EnableMenuItem(Info
->hMenu
, ID_EDIT_GLYPH
, uState
);
193 uState
= MF_BYCOMMAND
| !(Info
->CurrentFontWnd
&& IsClipboardFormatAvailable(uCharacterClipboardFormat
));
194 EnableMenuItem(Info
->hMenu
, ID_EDIT_PASTE
, uState
);
198 DoFileNew(IN PMAIN_WND_INFO Info
)
200 PFONT_OPEN_INFO OpenInfo
;
202 OpenInfo
= (PFONT_OPEN_INFO
) HeapAlloc( hProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(FONT_OPEN_INFO
) );
203 OpenInfo
->bCreateNew
= TRUE
;
205 CreateFontWindow(Info
, OpenInfo
);
209 DoFileOpen(IN PMAIN_WND_INFO Info
)
211 PFONT_OPEN_INFO OpenInfo
;
213 OpenInfo
= (PFONT_OPEN_INFO
) HeapAlloc( hProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(FONT_OPEN_INFO
) );
214 OpenInfo
->pszFileName
= HeapAlloc(hProcessHeap
, 0, MAX_PATH
);
215 OpenInfo
->pszFileName
[0] = 0;
217 if( DoOpenFile(OpenInfo
->pszFileName
) )
219 OpenInfo
->bCreateNew
= FALSE
;
220 CreateFontWindow(Info
, OpenInfo
);
225 DoFileSave(IN PMAIN_WND_INFO Info
, IN BOOL bSaveAs
)
227 DWORD dwBytesWritten
;
230 // Show the "Save" dialog
231 // - if "Save As" was clicked
232 // - if the file was not yet saved
233 // - if another format than the binary format was opened
234 if(bSaveAs
|| !Info
->CurrentFontWnd
->OpenInfo
->bBinaryFileOpened
)
236 if(!Info
->CurrentFontWnd
->OpenInfo
->pszFileName
)
238 Info
->CurrentFontWnd
->OpenInfo
->pszFileName
= (PWSTR
) HeapAlloc(hProcessHeap
, 0, MAX_PATH
);
239 Info
->CurrentFontWnd
->OpenInfo
->pszFileName
[0] = 0;
241 else if(!Info
->CurrentFontWnd
->OpenInfo
->bBinaryFileOpened
)
243 // For a file in another format, the user has to enter a new file name as well
244 Info
->CurrentFontWnd
->OpenInfo
->pszFileName
[0] = 0;
247 if( !DoSaveFile(Info
->CurrentFontWnd
->OpenInfo
->pszFileName
) )
251 // Save the binary font
252 hFile
= CreateFileW(Info
->CurrentFontWnd
->OpenInfo
->pszFileName
, GENERIC_WRITE
, FILE_SHARE_WRITE
, NULL
, OPEN_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
254 if(hFile
== INVALID_HANDLE_VALUE
)
256 LocalizedError( IDS_OPENERROR
, GetLastError() );
260 if( !WriteFile(hFile
, Info
->CurrentFontWnd
->Font
, sizeof(BITMAP_FONT
), &dwBytesWritten
, NULL
) )
261 LocalizedError( IDS_WRITEERROR
, GetLastError() );
267 CopyCurrentGlyph(IN PFONT_WND_INFO FontWndInfo
)
270 PUCHAR pCharacterBits
;
272 if(!OpenClipboard(NULL
))
277 hMem
= GlobalAlloc(GMEM_MOVEABLE
, 8);
278 pCharacterBits
= GlobalLock(hMem
);
279 RtlCopyMemory(pCharacterBits
, FontWndInfo
->Font
->Bits
+ FontWndInfo
->uSelectedCharacter
* 8, 8);
282 SetClipboardData(uCharacterClipboardFormat
, hMem
);
288 PasteIntoCurrentGlyph(IN PFONT_WND_INFO FontWndInfo
)
292 if(!IsClipboardFormatAvailable(uCharacterClipboardFormat
))
295 if(!OpenClipboard(NULL
))
298 hMem
= GetClipboardData(uCharacterClipboardFormat
);
301 PUCHAR pCharacterBits
;
303 pCharacterBits
= GlobalLock(hMem
);
310 RtlCopyMemory(FontWndInfo
->Font
->Bits
+ FontWndInfo
->uSelectedCharacter
* 8, pCharacterBits
, 8);
313 FontWndInfo
->OpenInfo
->bModified
= TRUE
;
315 GetCharacterPosition(FontWndInfo
->uSelectedCharacter
, &uFontRow
, &uFontColumn
);
316 GetCharacterRect(uFontRow
, uFontColumn
, &CharacterRect
);
317 InvalidateRect(FontWndInfo
->hFontBoxesWnd
, &CharacterRect
, FALSE
);
325 SetPasteButtonState(IN PMAIN_WND_INFO Info
)
327 SetToolbarButtonState(Info
,
329 (Info
->CurrentFontWnd
&& IsClipboardFormatAvailable(uCharacterClipboardFormat
)));
333 MenuCommand(IN INT nMenuItemID
, IN PMAIN_WND_INFO Info
)
347 SendMessageW(Info
->CurrentFontWnd
->hSelf
, WM_CLOSE
, 0, 0);
351 DoFileSave(Info
, FALSE
);
354 case ID_FILE_SAVE_AS
:
355 DoFileSave(Info
, TRUE
);
359 PostMessage(Info
->hMainWnd
, WM_CLOSE
, 0, 0);
364 EditCurrentGlyph(Info
->CurrentFontWnd
);
368 CopyCurrentGlyph(Info
->CurrentFontWnd
);
372 PasteIntoCurrentGlyph(Info
->CurrentFontWnd
);
376 case ID_WINDOW_TILE_HORZ
:
377 SendMessageW(Info
->hMdiClient
, WM_MDITILE
, MDITILE_HORIZONTAL
, 0);
380 case ID_WINDOW_TILE_VERT
:
381 SendMessageW(Info
->hMdiClient
, WM_MDITILE
, MDITILE_VERTICAL
, 0);
384 case ID_WINDOW_CASCADE
:
385 SendMessageW(Info
->hMdiClient
, WM_MDICASCADE
, 0, 0);
388 case ID_WINDOW_ARRANGE
:
389 SendMessageW(Info
->hMdiClient
, WM_MDIICONARRANGE
, 0, 0);
393 SendMessageW(Info
->hMdiClient
, WM_MDINEXT
, 0, 0);
398 DialogBoxW( hInstance
, MAKEINTRESOURCEW(IDD_ABOUT
), Info
->hMainWnd
, AboutDlgProc
);
406 MainWndSize(PMAIN_WND_INFO Info
, INT cx
, INT cy
)
414 dwp
= BeginDeferWindowPos(2);
420 GetWindowRect(Info
->hToolbar
, &ToolbarRect
);
421 iMdiTop
+= ToolbarRect
.bottom
- ToolbarRect
.top
;
423 dwp
= DeferWindowPos(dwp
, Info
->hToolbar
, NULL
, 0, 0, cx
, ToolbarRect
.bottom
- ToolbarRect
.top
, SWP_NOZORDER
);
430 dwp
= DeferWindowPos(dwp
, Info
->hMdiClient
, NULL
, 0, iMdiTop
, cx
, cy
- iMdiTop
, SWP_NOZORDER
);
435 EndDeferWindowPos(dwp
);
438 static LRESULT CALLBACK
439 MainWndProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
441 static HWND hNextClipboardViewer
;
445 Info
= (PMAIN_WND_INFO
) GetWindowLongW(hwnd
, GWLP_USERDATA
);
447 if(Info
|| uMsg
== WM_CREATE
)
452 if( MenuCommand( LOWORD(wParam
), Info
) )
457 case WM_CHANGECBCHAIN
:
458 if((HWND
)wParam
== hNextClipboardViewer
)
459 hNextClipboardViewer
= (HWND
)lParam
;
461 SendMessage(hNextClipboardViewer
, uMsg
, wParam
, lParam
);
466 if(Info
->FirstFontWnd
)
468 // Send WM_CLOSE to all subwindows, so they can prompt for saving unsaved files
469 PFONT_WND_INFO pNextWnd
;
472 pWnd
= Info
->FirstFontWnd
;
476 // The pWnd structure might already be destroyed after the WM_CLOSE, so we have to preserve the address of the next window here
477 pNextWnd
= pWnd
->NextFontWnd
;
479 // Send WM_USER_APPCLOSE, so we can check for a custom return value
480 // In this case, we check if the user clicked the "Cancel" button in one of the prompts and if so, we don't close the app
481 if( !SendMessage(pWnd
->hSelf
, WM_USER_APPCLOSE
, 0, 0) )
484 while( (pWnd
= pNextWnd
) );
489 Info
= (PMAIN_WND_INFO
)( ( (LPCREATESTRUCT
)lParam
)->lpCreateParams
);
490 Info
->hMainWnd
= hwnd
;
491 Info
->hMenu
= GetMenu(hwnd
);
492 SetWindowLongW(hwnd
, GWLP_USERDATA
, (LONG
)Info
);
494 hNextClipboardViewer
= SetClipboardViewer(hwnd
);
499 ShowWindow(hwnd
, Info
->nCmdShow
);
503 UnInitResources(Info
);
505 HeapFree(hProcessHeap
, 0, Info
);
506 SetWindowLongW(hwnd
, GWLP_USERDATA
, 0);
510 case WM_DRAWCLIPBOARD
:
511 SetPasteButtonState(Info
);
513 // Pass the message to the next clipboard window in the chain
514 SendMessage(hNextClipboardViewer
, uMsg
, wParam
, lParam
);
517 case WM_INITMENUPOPUP
:
522 MainWndSize( Info
, LOWORD(lParam
), HIWORD(lParam
) );
527 if(Info
&& Info
->hMdiClient
)
528 return DefFrameProcW(hwnd
, Info
->hMdiClient
, uMsg
, wParam
, lParam
);
530 return DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
534 CreateMainWindow(IN INT nCmdShow
, OUT PMAIN_WND_INFO
* Info
)
538 *Info
= (PMAIN_WND_INFO
) HeapAlloc( hProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(MAIN_WND_INFO
) );
542 (*Info
)->nCmdShow
= nCmdShow
;
544 hMainWnd
= CreateWindowExW(0,
547 WS_OVERLAPPEDWINDOW
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
,
553 LoadMenuW(hInstance
, MAKEINTRESOURCEW(IDM_MAINMENU
)),
560 HeapFree(hProcessHeap
, 0, *Info
);
567 InitMainWndClass(VOID
)
571 wc
.lpfnWndProc
= MainWndProc
;
572 wc
.hInstance
= hInstance
;
573 wc
.hCursor
= LoadCursor( NULL
, IDC_ARROW
);
574 wc
.hIcon
= LoadIconW( hInstance
, MAKEINTRESOURCEW(IDI_MAIN
) );
575 wc
.hbrBackground
= (HBRUSH
)( COLOR_BTNFACE
+ 1 );
576 wc
.lpszClassName
= szMainWndClass
;
578 return RegisterClassW(&wc
) != 0;
582 UnInitMainWndClass(VOID
)
584 UnregisterClassW(szMainWndClass
, hInstance
);