2 * PROJECT: ReactOS VGA Font Editor
3 * LICENSE: GNU General Public License Version 2.0 or any later version
4 * FILE: devutils/vgafontedit/mainwnd.c
5 * PURPOSE: Implements the main window of the application
6 * COPYRIGHT: Copyright 2008 Colin Finck <mail@colinfinck.de>
11 static const WCHAR szMainWndClass
[] = L
"VGAFontEditMainWndClass";
14 InitResources(IN PMAIN_WND_INFO Info
)
22 hMemDC
= CreateCompatibleDC(NULL
);
23 hMainDC
= GetDC(Info
->hMainWnd
);
25 // Create the "Box" bitmap
26 Info
->hBoxBmp
= CreateCompatibleBitmap(hMainDC
, CHARACTER_BOX_WIDTH
, CHARACTER_BOX_HEIGHT
);
27 hBitmapOld
= SelectObject(hMemDC
, Info
->hBoxBmp
);
31 rect
.right
= CHARACTER_INFO_BOX_WIDTH
;
32 rect
.bottom
= CHARACTER_INFO_BOX_HEIGHT
;
33 FillRect( hMemDC
, &rect
, (HBRUSH
)(COLOR_BTNFACE
+ 1) );
35 hPenOld
= SelectObject( hMemDC
, GetStockObject(WHITE_PEN
) );
36 Rectangle(hMemDC
, 0, 0, CHARACTER_INFO_BOX_WIDTH
- 1, 2);
37 Rectangle(hMemDC
, 0, 2, 2, CHARACTER_INFO_BOX_HEIGHT
- 1);
38 hPen
= SelectObject(hMemDC
, hPenOld
);
40 hPen
= CreatePen( PS_SOLID
, 1, RGB(128, 128, 128) );
41 hPenOld
= SelectObject(hMemDC
, hPen
);
42 Rectangle(hMemDC
, 1, CHARACTER_INFO_BOX_HEIGHT
- 2, CHARACTER_INFO_BOX_WIDTH
, CHARACTER_INFO_BOX_HEIGHT
);
43 Rectangle(hMemDC
, CHARACTER_INFO_BOX_WIDTH
- 2, 1, CHARACTER_INFO_BOX_WIDTH
, CHARACTER_INFO_BOX_HEIGHT
- 2);
45 SetPixel( hMemDC
, CHARACTER_INFO_BOX_WIDTH
- 1, 0, RGB(128, 128, 128) );
46 SetPixel( hMemDC
, 0, CHARACTER_INFO_BOX_HEIGHT
- 1, RGB(128, 128, 128) );
47 SelectObject(hMemDC
, hBitmapOld
);
49 hPen
= SelectObject(hMemDC
, hPenOld
);
52 ReleaseDC(Info
->hMainWnd
, hMainDC
);
56 UnInitResources(IN PMAIN_WND_INFO Info
)
58 DeleteObject(Info
->hBoxBmp
);
62 AddToolbarButton(IN PMAIN_WND_INFO Info
, IN INT iBitmap
, IN INT idCommand
, IN UINT uID
)
67 if( AllocAndLoadString(&pszTooltip
, uID
) )
69 tbb
.fsState
= TBSTATE_ENABLED
;
70 tbb
.iBitmap
= iBitmap
;
71 tbb
.idCommand
= idCommand
;
72 tbb
.iString
= (INT_PTR
)pszTooltip
;
74 SendMessageW( Info
->hToolbar
, TB_ADDBUTTONSW
, 1, (LPARAM
)&tbb
);
75 HeapFree(hProcessHeap
, 0, pszTooltip
);
80 SetToolbarButtonState(IN PMAIN_WND_INFO Info
, INT idCommand
, BOOL bEnabled
)
82 TBBUTTONINFOW tbbi
= {0,};
84 tbbi
.cbSize
= sizeof(tbbi
);
85 tbbi
.dwMask
= TBIF_STATE
;
86 tbbi
.fsState
= (bEnabled
? TBSTATE_ENABLED
: 0);
88 SendMessageW(Info
->hToolbar
, TB_SETBUTTONINFOW
, idCommand
, (LPARAM
)&tbbi
);
92 SetToolbarFileButtonState(IN PMAIN_WND_INFO Info
, BOOL bEnabled
)
94 SetToolbarButtonState(Info
, ID_FILE_SAVE
, bEnabled
);
95 SetToolbarButtonState(Info
, ID_EDIT_GLYPH
, bEnabled
);
96 SetToolbarButtonState(Info
, ID_EDIT_COPY
, bEnabled
);
100 AddToolbarSeparator(IN PMAIN_WND_INFO Info
)
104 tbb
.fsStyle
= BTNS_SEP
;
106 SendMessageW( Info
->hToolbar
, TB_ADDBUTTONSW
, 1, (LPARAM
)&tbb
);
110 InitMainWnd(IN PMAIN_WND_INFO Info
)
112 CLIENTCREATESTRUCT ccs
;
114 INT iStandardBitmaps
;
118 Info
->hToolbar
= CreateWindowExW(0,
121 WS_VISIBLE
| WS_CHILD
| TBSTYLE_TOOLTIPS
,
131 // Identify the used Common Controls version
132 SendMessageW(Info
->hToolbar
, TB_BUTTONSTRUCTSIZE
, sizeof(TBBUTTON
), 0);
135 SendMessageW(Info
->hToolbar
, TB_SETMAXTEXTROWS
, 0, 0);
137 // Add the toolbar bitmaps
138 tbab
.hInst
= HINST_COMMCTRL
;
139 tbab
.nID
= IDB_STD_SMALL_COLOR
;
140 iStandardBitmaps
= (INT
)SendMessageW(Info
->hToolbar
, TB_ADDBITMAP
, 0, (LPARAM
)&tbab
);
142 tbab
.hInst
= hInstance
;
143 tbab
.nID
= IDB_MAIN_TOOLBAR
;
144 iCustomBitmaps
= (INT
)SendMessageW(Info
->hToolbar
, TB_ADDBITMAP
, 0, (LPARAM
)&tbab
);
146 // Add the toolbar buttons
147 AddToolbarButton(Info
, iStandardBitmaps
+ STD_FILENEW
, ID_FILE_NEW
, IDS_TOOLTIP_NEW
);
148 AddToolbarButton(Info
, iStandardBitmaps
+ STD_FILEOPEN
, ID_FILE_OPEN
, IDS_TOOLTIP_OPEN
);
149 AddToolbarButton(Info
, iStandardBitmaps
+ STD_FILESAVE
, ID_FILE_SAVE
, IDS_TOOLTIP_SAVE
);
150 AddToolbarSeparator(Info
);
151 AddToolbarButton(Info
, iCustomBitmaps
+ TOOLBAR_EDIT_GLYPH
, ID_EDIT_GLYPH
, IDS_TOOLTIP_EDIT_GLYPH
);
152 AddToolbarSeparator(Info
);
153 AddToolbarButton(Info
, iStandardBitmaps
+ STD_COPY
, ID_EDIT_COPY
, IDS_TOOLTIP_COPY
);
154 AddToolbarButton(Info
, iStandardBitmaps
+ STD_PASTE
, ID_EDIT_PASTE
, IDS_TOOLTIP_PASTE
);
156 SetToolbarFileButtonState(Info
, FALSE
);
157 SetPasteButtonState(Info
);
159 // Add the MDI client area
160 ccs
.hWindowMenu
= GetSubMenu(Info
->hMenu
, 2);
161 ccs
.idFirstChild
= ID_MDI_FIRSTCHILD
;
163 Info
->hMdiClient
= CreateWindowExW(WS_EX_CLIENTEDGE
,
166 WS_VISIBLE
| WS_CHILD
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
| WS_VSCROLL
| WS_HSCROLL
,
176 // Initialize the file handling
177 FileInitialize(Info
->hMainWnd
);
181 InitMenuPopup(IN PMAIN_WND_INFO Info
)
185 uState
= MF_BYCOMMAND
| !(Info
->CurrentFontWnd
);
187 EnableMenuItem(Info
->hMenu
, ID_FILE_CLOSE
, uState
);
188 EnableMenuItem(Info
->hMenu
, ID_FILE_SAVE
, uState
);
189 EnableMenuItem(Info
->hMenu
, ID_FILE_SAVE_AS
, uState
);
191 EnableMenuItem(Info
->hMenu
, ID_EDIT_COPY
, uState
);
192 EnableMenuItem(Info
->hMenu
, ID_EDIT_GLYPH
, uState
);
194 uState
= MF_BYCOMMAND
| !(Info
->CurrentFontWnd
&& IsClipboardFormatAvailable(uCharacterClipboardFormat
));
195 EnableMenuItem(Info
->hMenu
, ID_EDIT_PASTE
, uState
);
199 DoFileNew(IN PMAIN_WND_INFO Info
)
201 PFONT_OPEN_INFO OpenInfo
;
203 OpenInfo
= (PFONT_OPEN_INFO
) HeapAlloc( hProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(FONT_OPEN_INFO
) );
204 OpenInfo
->bCreateNew
= TRUE
;
206 CreateFontWindow(Info
, OpenInfo
);
210 DoFileOpen(IN PMAIN_WND_INFO Info
)
212 PFONT_OPEN_INFO OpenInfo
;
214 OpenInfo
= (PFONT_OPEN_INFO
) HeapAlloc( hProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(FONT_OPEN_INFO
) );
215 OpenInfo
->pszFileName
= HeapAlloc(hProcessHeap
, 0, MAX_PATH
);
216 OpenInfo
->pszFileName
[0] = 0;
218 if( DoOpenFile(OpenInfo
->pszFileName
) )
220 OpenInfo
->bCreateNew
= FALSE
;
221 CreateFontWindow(Info
, OpenInfo
);
226 DoFileSave(IN PMAIN_WND_INFO Info
, IN BOOL bSaveAs
)
228 DWORD dwBytesWritten
;
231 // Show the "Save" dialog
232 // - if "Save As" was clicked
233 // - if the file was not yet saved
234 // - if another format than the binary format was opened
235 if(bSaveAs
|| !Info
->CurrentFontWnd
->OpenInfo
->bBinaryFileOpened
)
237 if(!Info
->CurrentFontWnd
->OpenInfo
->pszFileName
)
239 Info
->CurrentFontWnd
->OpenInfo
->pszFileName
= (PWSTR
) HeapAlloc(hProcessHeap
, 0, MAX_PATH
);
240 Info
->CurrentFontWnd
->OpenInfo
->pszFileName
[0] = 0;
242 else if(!Info
->CurrentFontWnd
->OpenInfo
->bBinaryFileOpened
)
244 // For a file in another format, the user has to enter a new file name as well
245 Info
->CurrentFontWnd
->OpenInfo
->pszFileName
[0] = 0;
248 if( !DoSaveFile(Info
->CurrentFontWnd
->OpenInfo
->pszFileName
) )
252 // Save the binary font
253 hFile
= CreateFileW(Info
->CurrentFontWnd
->OpenInfo
->pszFileName
, GENERIC_WRITE
, FILE_SHARE_WRITE
, NULL
, OPEN_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
255 if(hFile
== INVALID_HANDLE_VALUE
)
257 LocalizedError( IDS_OPENERROR
, GetLastError() );
261 if( !WriteFile(hFile
, Info
->CurrentFontWnd
->Font
, sizeof(BITMAP_FONT
), &dwBytesWritten
, NULL
) )
262 LocalizedError( IDS_WRITEERROR
, GetLastError() );
268 CopyCurrentGlyph(IN PFONT_WND_INFO FontWndInfo
)
271 PUCHAR pCharacterBits
;
273 if(!OpenClipboard(NULL
))
278 hMem
= GlobalAlloc(GMEM_MOVEABLE
, 8);
279 pCharacterBits
= GlobalLock(hMem
);
280 RtlCopyMemory(pCharacterBits
, FontWndInfo
->Font
->Bits
+ FontWndInfo
->uSelectedCharacter
* 8, 8);
283 SetClipboardData(uCharacterClipboardFormat
, hMem
);
289 PasteIntoCurrentGlyph(IN PFONT_WND_INFO FontWndInfo
)
293 if(!IsClipboardFormatAvailable(uCharacterClipboardFormat
))
296 if(!OpenClipboard(NULL
))
299 hMem
= GetClipboardData(uCharacterClipboardFormat
);
302 PUCHAR pCharacterBits
;
304 pCharacterBits
= GlobalLock(hMem
);
311 RtlCopyMemory(FontWndInfo
->Font
->Bits
+ FontWndInfo
->uSelectedCharacter
* 8, pCharacterBits
, 8);
314 FontWndInfo
->OpenInfo
->bModified
= TRUE
;
316 GetCharacterPosition(FontWndInfo
->uSelectedCharacter
, &uFontRow
, &uFontColumn
);
317 GetCharacterRect(uFontRow
, uFontColumn
, &CharacterRect
);
318 InvalidateRect(FontWndInfo
->hFontBoxesWnd
, &CharacterRect
, FALSE
);
326 SetPasteButtonState(IN PMAIN_WND_INFO Info
)
328 SetToolbarButtonState(Info
,
330 (Info
->CurrentFontWnd
&& IsClipboardFormatAvailable(uCharacterClipboardFormat
)));
334 MenuCommand(IN INT nMenuItemID
, IN PMAIN_WND_INFO Info
)
348 SendMessageW(Info
->CurrentFontWnd
->hSelf
, WM_CLOSE
, 0, 0);
352 DoFileSave(Info
, FALSE
);
355 case ID_FILE_SAVE_AS
:
356 DoFileSave(Info
, TRUE
);
360 PostMessage(Info
->hMainWnd
, WM_CLOSE
, 0, 0);
365 EditCurrentGlyph(Info
->CurrentFontWnd
);
369 CopyCurrentGlyph(Info
->CurrentFontWnd
);
373 PasteIntoCurrentGlyph(Info
->CurrentFontWnd
);
377 case ID_WINDOW_TILE_HORZ
:
378 SendMessageW(Info
->hMdiClient
, WM_MDITILE
, MDITILE_HORIZONTAL
, 0);
381 case ID_WINDOW_TILE_VERT
:
382 SendMessageW(Info
->hMdiClient
, WM_MDITILE
, MDITILE_VERTICAL
, 0);
385 case ID_WINDOW_CASCADE
:
386 SendMessageW(Info
->hMdiClient
, WM_MDICASCADE
, 0, 0);
389 case ID_WINDOW_ARRANGE
:
390 SendMessageW(Info
->hMdiClient
, WM_MDIICONARRANGE
, 0, 0);
394 SendMessageW(Info
->hMdiClient
, WM_MDINEXT
, 0, 0);
399 DialogBoxW( hInstance
, MAKEINTRESOURCEW(IDD_ABOUT
), Info
->hMainWnd
, AboutDlgProc
);
407 MainWndSize(PMAIN_WND_INFO Info
, INT cx
, INT cy
)
415 dwp
= BeginDeferWindowPos(2);
421 GetWindowRect(Info
->hToolbar
, &ToolbarRect
);
422 iMdiTop
+= ToolbarRect
.bottom
- ToolbarRect
.top
;
424 dwp
= DeferWindowPos(dwp
, Info
->hToolbar
, NULL
, 0, 0, cx
, ToolbarRect
.bottom
- ToolbarRect
.top
, SWP_NOZORDER
);
431 dwp
= DeferWindowPos(dwp
, Info
->hMdiClient
, NULL
, 0, iMdiTop
, cx
, cy
- iMdiTop
, SWP_NOZORDER
);
436 EndDeferWindowPos(dwp
);
439 static LRESULT CALLBACK
440 MainWndProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
442 static HWND hNextClipboardViewer
;
446 Info
= (PMAIN_WND_INFO
) GetWindowLongW(hwnd
, GWLP_USERDATA
);
448 if(Info
|| uMsg
== WM_CREATE
)
453 if( MenuCommand( LOWORD(wParam
), Info
) )
458 case WM_CHANGECBCHAIN
:
459 if((HWND
)wParam
== hNextClipboardViewer
)
460 hNextClipboardViewer
= (HWND
)lParam
;
462 SendMessage(hNextClipboardViewer
, uMsg
, wParam
, lParam
);
467 if(Info
->FirstFontWnd
)
469 // Send WM_CLOSE to all subwindows, so they can prompt for saving unsaved files
470 PFONT_WND_INFO pNextWnd
;
473 pWnd
= Info
->FirstFontWnd
;
477 // The pWnd structure might already be destroyed after the WM_CLOSE, so we have to preserve the address of the next window here
478 pNextWnd
= pWnd
->NextFontWnd
;
480 // Send WM_USER_APPCLOSE, so we can check for a custom return value
481 // 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
482 if( !SendMessage(pWnd
->hSelf
, WM_USER_APPCLOSE
, 0, 0) )
485 while( (pWnd
= pNextWnd
) );
490 Info
= (PMAIN_WND_INFO
)( ( (LPCREATESTRUCT
)lParam
)->lpCreateParams
);
491 Info
->hMainWnd
= hwnd
;
492 Info
->hMenu
= GetMenu(hwnd
);
493 SetWindowLongW(hwnd
, GWLP_USERDATA
, (LONG
)Info
);
495 hNextClipboardViewer
= SetClipboardViewer(hwnd
);
500 ShowWindow(hwnd
, Info
->nCmdShow
);
504 UnInitResources(Info
);
506 HeapFree(hProcessHeap
, 0, Info
);
507 SetWindowLongW(hwnd
, GWLP_USERDATA
, 0);
511 case WM_DRAWCLIPBOARD
:
512 SetPasteButtonState(Info
);
514 // Pass the message to the next clipboard window in the chain
515 SendMessage(hNextClipboardViewer
, uMsg
, wParam
, lParam
);
518 case WM_INITMENUPOPUP
:
523 MainWndSize( Info
, LOWORD(lParam
), HIWORD(lParam
) );
528 if(Info
&& Info
->hMdiClient
)
529 return DefFrameProcW(hwnd
, Info
->hMdiClient
, uMsg
, wParam
, lParam
);
531 return DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
535 CreateMainWindow(IN INT nCmdShow
, OUT PMAIN_WND_INFO
* Info
)
539 *Info
= (PMAIN_WND_INFO
) HeapAlloc( hProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(MAIN_WND_INFO
) );
543 (*Info
)->nCmdShow
= nCmdShow
;
545 hMainWnd
= CreateWindowExW(0,
548 WS_OVERLAPPEDWINDOW
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
,
554 LoadMenuW(hInstance
, MAKEINTRESOURCEW(IDM_MAINMENU
)),
561 HeapFree(hProcessHeap
, 0, *Info
);
568 InitMainWndClass(VOID
)
572 wc
.lpfnWndProc
= MainWndProc
;
573 wc
.hInstance
= hInstance
;
574 wc
.hCursor
= LoadCursor( NULL
, IDC_ARROW
);
575 wc
.hIcon
= LoadIconW( hInstance
, MAKEINTRESOURCEW(IDI_MAIN
) );
576 wc
.hbrBackground
= (HBRUSH
)( COLOR_BTNFACE
+ 1 );
577 wc
.lpszClassName
= szMainWndClass
;
579 return RegisterClassW(&wc
) != 0;
583 UnInitMainWndClass(VOID
)
585 UnregisterClassW(szMainWndClass
, hInstance
);