bd83e56a04a1623846c9a3ae746ad336cb2ce48a
[reactos.git] / base / applications / mspaint / main.cpp
1 /*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL
4 * FILE: base/applications/mspaint/main.cpp
5 * PURPOSE: Initializing everything
6 * PROGRAMMERS: Benedikt Freisen
7 */
8
9 #include "precomp.h"
10
11 #ifdef _DEBUG
12 #include <crtdbg.h>
13 #endif
14
15 /* FUNCTIONS ********************************************************/
16
17 POINT start;
18 POINT last;
19
20 ToolsModel toolsModel;
21
22 SelectionModel selectionModel;
23
24 PaletteModel paletteModel;
25
26 RegistrySettings registrySettings;
27
28 ImageModel imageModel;
29 BOOL askBeforeEnlarging = FALSE; // TODO: initialize from registry
30
31 HWND hStatusBar;
32 CHOOSECOLOR choosecolor;
33 OPENFILENAME ofn;
34 OPENFILENAME sfn;
35 HICON hNontranspIcon;
36 HICON hTranspIcon;
37
38 HINSTANCE hProgInstance;
39
40 TCHAR filepathname[1000];
41 BOOL isAFile = FALSE;
42 BOOL imageSaved = FALSE;
43 int fileSize;
44 int fileHPPM = 2834;
45 int fileVPPM = 2834;
46 SYSTEMTIME fileTime;
47
48 BOOL showGrid = FALSE;
49 BOOL showMiniature = FALSE;
50
51 CMainWindow mainWindow;
52 CFullscreenWindow fullscreenWindow;
53 CMiniatureWindow miniature;
54 CToolBox toolBoxContainer;
55 CToolSettingsWindow toolSettingsWindow;
56 CPaletteWindow paletteWindow;
57 CCanvasWindow canvasWindow;
58 CSelectionWindow selectionWindow;
59 CImgAreaWindow imageArea;
60 CSizeboxWindow sizeboxLeftTop;
61 CSizeboxWindow sizeboxCenterTop;
62 CSizeboxWindow sizeboxRightTop;
63 CSizeboxWindow sizeboxLeftCenter;
64 CSizeboxWindow sizeboxRightCenter;
65 CSizeboxWindow sizeboxLeftBottom;
66 CSizeboxWindow sizeboxCenterBottom;
67 CSizeboxWindow sizeboxRightBottom;
68 CTextEditWindow textEditWindow;
69
70 // get file name extension from filter string
71 static BOOL
72 FileExtFromFilter(LPTSTR pExt, LPCTSTR pTitle, OPENFILENAME *pOFN)
73 {
74 LPTSTR pchExt = pExt;
75 *pchExt = 0;
76
77 DWORD nIndex = 1;
78 for (LPCTSTR pch = pOFN->lpstrFilter; *pch; ++nIndex)
79 {
80 pch += lstrlen(pch) + 1;
81 if (pOFN->nFilterIndex == nIndex)
82 {
83 for (++pch; *pch && *pch != _T(';'); ++pch)
84 {
85 *pchExt++ = *pch;
86 }
87 *pchExt = 0;
88 CharLower(pExt);
89 return TRUE;
90 }
91 pch += lstrlen(pch) + 1;
92 }
93 return FALSE;
94 }
95
96 // Hook procedure for OPENFILENAME to change the file name extension
97 static UINT_PTR APIENTRY
98 OFNHookProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
99 {
100 HWND hParent;
101 OFNOTIFY *pon;
102 switch (uMsg)
103 {
104 case WM_NOTIFY:
105 pon = (OFNOTIFY *)lParam;
106 if (pon->hdr.code == CDN_TYPECHANGE)
107 {
108 hParent = GetParent(hwnd);
109 TCHAR Path[MAX_PATH];
110 SendMessage(hParent, CDM_GETFILEPATH, _countof(Path), (LPARAM)Path);
111 LPTSTR pchTitle = _tcsrchr(Path, _T('\\'));
112 if (pchTitle == NULL)
113 pchTitle = _tcsrchr(Path, _T('/'));
114
115 LPTSTR pch = _tcsrchr((pchTitle ? pchTitle : Path), _T('.'));
116 if (pch && pchTitle)
117 {
118 pchTitle++;
119 *pch = 0;
120 FileExtFromFilter(pch, pchTitle, pon->lpOFN);
121 SendMessage(hParent, CDM_SETCONTROLTEXT, 0x047c, (LPARAM)pchTitle);
122 lstrcpyn(pon->lpOFN->lpstrFile, Path, pon->lpOFN->nMaxFile);
123 }
124 }
125 break;
126 }
127 return 0;
128 }
129
130 /* entry point */
131
132 int WINAPI
133 _tWinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPTSTR lpszArgument, INT nCmdShow)
134 {
135 HWND hwnd; /* This is the handle for our window */
136 MSG messages; /* Here messages to the application are saved */
137
138 HMENU menu;
139 HACCEL haccel;
140
141 TCHAR sfnFilename[1000];
142 TCHAR sfnFiletitle[256];
143 TCHAR ofnFilename[1000];
144 TCHAR ofnFiletitle[256];
145 TCHAR miniaturetitle[100];
146 static COLORREF custColors[16] = {
147 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff,
148 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff
149 };
150
151 #ifdef _DEBUG
152 /* Report any memory leaks on exit */
153 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
154 #endif
155
156 hProgInstance = hThisInstance;
157
158 /* initialize common controls library */
159 INITCOMMONCONTROLSEX iccx;
160 iccx.dwSize = sizeof(iccx);
161 iccx.dwICC = ICC_STANDARD_CLASSES | ICC_USEREX_CLASSES | ICC_BAR_CLASSES;
162 InitCommonControlsEx(&iccx);
163
164 LoadString(hThisInstance, IDS_DEFAULTFILENAME, filepathname, _countof(filepathname));
165 CPath pathFileName(filepathname);
166 pathFileName.StripPath();
167 CString strTitle;
168 strTitle.Format(IDS_WINDOWTITLE, (LPCTSTR)pathFileName);
169 LoadString(hThisInstance, IDS_MINIATURETITLE, miniaturetitle, _countof(miniaturetitle));
170
171 /* load settings from registry */
172 registrySettings.Load(nCmdShow);
173 showMiniature = registrySettings.ShowThumbnail;
174 imageModel.Crop(registrySettings.BMPWidth, registrySettings.BMPHeight);
175
176 /* create main window */
177 RECT mainWindowPos = registrySettings.WindowPlacement.rcNormalPosition;
178 hwnd = mainWindow.Create(HWND_DESKTOP, mainWindowPos, strTitle, WS_OVERLAPPEDWINDOW);
179
180 RECT fullscreenWindowPos = {0, 0, 100, 100};
181 fullscreenWindow.Create(HWND_DESKTOP, fullscreenWindowPos, NULL, WS_POPUPWINDOW | WS_MAXIMIZE);
182
183 RECT miniaturePos = {(LONG) registrySettings.ThumbXPos, (LONG) registrySettings.ThumbYPos,
184 (LONG) registrySettings.ThumbXPos + (LONG) registrySettings.ThumbWidth,
185 (LONG) registrySettings.ThumbYPos + (LONG) registrySettings.ThumbHeight};
186 miniature.Create(hwnd, miniaturePos, miniaturetitle,
187 WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME, WS_EX_PALETTEWINDOW);
188 miniature.ShowWindow(showMiniature ? SW_SHOW : SW_HIDE);
189
190 /* loading and setting the window menu from resource */
191 menu = LoadMenu(hThisInstance, MAKEINTRESOURCE(ID_MENU));
192 SetMenu(hwnd, menu);
193 haccel = LoadAccelerators(hThisInstance, MAKEINTRESOURCE(800));
194
195 /* preloading the draw transparent/nontransparent icons for later use */
196 hNontranspIcon =
197 (HICON) LoadImage(hThisInstance, MAKEINTRESOURCE(IDI_NONTRANSPARENT), IMAGE_ICON, 40, 30, LR_DEFAULTCOLOR);
198 hTranspIcon =
199 (HICON) LoadImage(hThisInstance, MAKEINTRESOURCE(IDI_TRANSPARENT), IMAGE_ICON, 40, 30, LR_DEFAULTCOLOR);
200
201 RECT toolBoxContainerPos = {2, 2, 2 + 52, 2 + 350};
202 toolBoxContainer.Create(hwnd, toolBoxContainerPos, NULL, WS_CHILD | WS_VISIBLE);
203 /* creating the tool settings child window */
204 RECT toolSettingsWindowPos = {5, 208, 5 + 42, 208 + 140};
205 toolSettingsWindow.Create(toolBoxContainer.m_hWnd, toolSettingsWindowPos, NULL, WS_CHILD | WS_VISIBLE);
206
207 /* creating the palette child window */
208 RECT paletteWindowPos = {56, 9, 56 + 255, 9 + 32};
209 paletteWindow.Create(hwnd, paletteWindowPos, NULL, WS_CHILD | WS_VISIBLE, WS_EX_STATICEDGE);
210
211 // creating the canvas
212 RECT canvasWindowPos = {0, 0, 0 + 500, 0 + 500};
213 canvasWindow.Create(hwnd, canvasWindowPos, NULL,
214 WS_CHILD | WS_GROUP | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE, WS_EX_CLIENTEDGE);
215
216 /* creating the status bar */
217 hStatusBar =
218 CreateWindowEx(0, STATUSCLASSNAME, NULL, SBARS_SIZEGRIP | WS_CHILD, 0, 0, 0, 0, hwnd,
219 NULL, hThisInstance, NULL);
220 SendMessage(hStatusBar, SB_SETMINHEIGHT, 21, 0);
221 if (registrySettings.ShowStatusBar)
222 ShowWindow(hStatusBar, SW_SHOWNOACTIVATE);
223
224 // Creating the window inside the canvas
225 RECT imageAreaPos = {GRIP_SIZE, GRIP_SIZE, GRIP_SIZE + imageModel.GetWidth(), GRIP_SIZE + imageModel.GetHeight()};
226 imageArea.Create(canvasWindow.m_hWnd, imageAreaPos, NULL, WS_CHILD | WS_VISIBLE);
227
228 /* create selection window (initially hidden) */
229 RECT selectionWindowPos = {350, 0, 350 + 100, 0 + 100};
230 selectionWindow.Create(imageArea.m_hWnd, selectionWindowPos, NULL, WS_CHILD | BS_OWNERDRAW);
231
232 if (__argc >= 2)
233 {
234 DoLoadImageFile(mainWindow, __targv[1], TRUE);
235 }
236
237 imageModel.ClearHistory();
238
239 /* initializing the CHOOSECOLOR structure for use with ChooseColor */
240 ZeroMemory(&choosecolor, sizeof(choosecolor));
241 choosecolor.lStructSize = sizeof(CHOOSECOLOR);
242 choosecolor.hwndOwner = hwnd;
243 choosecolor.rgbResult = 0x00ffffff;
244 choosecolor.lpCustColors = custColors;
245
246 /* initializing the OPENFILENAME structure for use with GetOpenFileName and GetSaveFileName */
247 ofnFilename[0] = 0;
248 CString strImporters;
249 CSimpleArray<GUID> aguidFileTypesI;
250 CString strAllPictureFiles;
251 strAllPictureFiles.LoadString(hThisInstance, IDS_ALLPICTUREFILES);
252 CImage::GetImporterFilterString(strImporters, aguidFileTypesI, strAllPictureFiles, CImage::excludeDefaultLoad, _T('\0'));
253 // CAtlStringW strAllFiles;
254 // strAllFiles.LoadString(hThisInstance, IDS_ALLFILES);
255 // strImporters = strAllFiles + CAtlStringW(_T("|*.*|")).Replace('|', '\0') + strImporters;
256 ZeroMemory(&ofn, sizeof(OPENFILENAME));
257 ofn.lStructSize = sizeof(OPENFILENAME);
258 ofn.hwndOwner = hwnd;
259 ofn.hInstance = hThisInstance;
260 ofn.lpstrFilter = strImporters;
261 ofn.lpstrFile = ofnFilename;
262 ofn.nMaxFile = _countof(ofnFilename);
263 ofn.lpstrFileTitle = ofnFiletitle;
264 ofn.nMaxFileTitle = _countof(ofnFiletitle);
265 ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY;
266 ofn.lpstrDefExt = L"png";
267
268 CopyMemory(sfnFilename, filepathname, sizeof(filepathname));
269 CString strExporters;
270 CSimpleArray<GUID> aguidFileTypesE;
271 CImage::GetExporterFilterString(strExporters, aguidFileTypesE, NULL, CImage::excludeDefaultSave, _T('\0'));
272 ZeroMemory(&sfn, sizeof(OPENFILENAME));
273 sfn.lStructSize = sizeof(OPENFILENAME);
274 sfn.hwndOwner = hwnd;
275 sfn.hInstance = hThisInstance;
276 sfn.lpstrFilter = strExporters;
277 sfn.lpstrFile = sfnFilename;
278 sfn.nMaxFile = _countof(sfnFilename);
279 sfn.lpstrFileTitle = sfnFiletitle;
280 sfn.nMaxFileTitle = _countof(sfnFiletitle);
281 sfn.Flags = OFN_EXPLORER | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_EXPLORER | OFN_ENABLEHOOK;
282 sfn.lpfnHook = OFNHookProc;
283 sfn.lpstrDefExt = L"png";
284 // Choose PNG
285 for (INT i = 0; i < aguidFileTypesE.GetSize(); ++i)
286 {
287 if (aguidFileTypesE[i] == Gdiplus::ImageFormatPNG)
288 {
289 sfn.nFilterIndex = i + 1;
290 break;
291 }
292 }
293
294 /* creating the size boxes */
295 RECT sizeboxPos = {0, 0, GRIP_SIZE, GRIP_SIZE};
296 sizeboxLeftTop.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
297 sizeboxCenterTop.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
298 sizeboxRightTop.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
299 sizeboxLeftCenter.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
300 sizeboxRightCenter.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
301 sizeboxLeftBottom.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
302 sizeboxCenterBottom.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
303 sizeboxRightBottom.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
304 /* placing the size boxes around the image */
305 imageArea.SendMessage(WM_SIZE, 0, 0);
306
307 /* Make the window visible on the screen */
308 ShowWindow(hwnd, registrySettings.WindowPlacement.showCmd);
309
310 /* inform the system, that the main window accepts dropped files */
311 DragAcceptFiles(hwnd, TRUE);
312
313 /* Run the message loop. It will run until GetMessage() returns 0 */
314 while (GetMessage(&messages, NULL, 0, 0))
315 {
316 if (fontsDialog.IsWindow() && IsDialogMessage(fontsDialog, &messages))
317 continue;
318
319 if (TranslateAccelerator(hwnd, haccel, &messages))
320 continue;
321
322 /* Translate virtual-key messages into character messages */
323 TranslateMessage(&messages);
324 /* Send message to WindowProcedure */
325 DispatchMessage(&messages);
326 }
327
328 /* write back settings to registry */
329 registrySettings.ShowThumbnail = showMiniature;
330 registrySettings.BMPWidth = imageModel.GetWidth();
331 registrySettings.BMPHeight = imageModel.GetHeight();
332 registrySettings.Store();
333
334 /* The program return-value is 0 - The value that PostQuitMessage() gave */
335 return messages.wParam;
336 }