[MSPAINT_NEW] split CMainWindow: factor out CImgAreaWindow and CMiniatureWindow ...
[reactos.git] / reactos / base / applications / mspaint_new / main.cpp
1 /*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL
4 * FILE: base/applications/mspaint_new/main.cpp
5 * PURPOSE: Initializing everything
6 * PROGRAMMERS: Benedikt Freisen
7 */
8
9 /* INCLUDES *********************************************************/
10
11 #include "precomp.h"
12
13 /* FUNCTIONS ********************************************************/
14
15 HDC hDrawingDC;
16 HDC hSelDC;
17 int *bmAddress;
18 BITMAPINFO bitmapinfo;
19 int imgXRes = 400;
20 int imgYRes = 300;
21
22 int widthSetInDlg;
23 int heightSetInDlg;
24
25 STRETCHSKEW stretchSkew;
26
27 HBITMAP hBms[HISTORYSIZE];
28 int currInd = 0;
29 int undoSteps = 0;
30 int redoSteps = 0;
31 BOOL imageSaved = TRUE;
32
33 POINT start;
34 POINT last;
35 int lineWidth = 1;
36 int shapeStyle = 0;
37 int brushStyle = 0;
38 int activeTool = TOOL_PEN;
39 int airBrushWidth = 5;
40 int rubberRadius = 4;
41 int transpBg = 0;
42 int zoom = 1000;
43 RECT rectSel_src;
44 RECT rectSel_dest;
45 HBITMAP hSelBm;
46 HBITMAP hSelMask;
47 LOGFONT lfTextFont;
48 HFONT hfontTextFont;
49 HWND hwndEditCtl;
50 LPTSTR textToolText = NULL;
51 int textToolTextMaxLen = 0;
52
53 /* array holding palette colors; may be changed by the user during execution */
54 int palColors[28];
55
56 /* modern palette */
57 int modernPalColors[28] = { 0x000000, 0x464646, 0x787878, 0x300099, 0x241ced, 0x0078ff, 0x0ec2ff,
58 0x00f2ff, 0x1de6a8, 0x4cb122, 0xefb700, 0xf36d4d, 0x99362f, 0x98316f,
59 0xffffff, 0xdcdcdc, 0xb4b4b4, 0x3c5a9c, 0xb1a3ff, 0x7aaae5, 0x9ce4f5,
60 0xbdf9ff, 0xbcf9d3, 0x61bb9d, 0xead999, 0xd19a70, 0x8e6d54, 0xd5a5b5
61 };
62
63 /* older palette containing VGA colors */
64 int oldPalColors[28] = { 0x000000, 0x808080, 0x000080, 0x008080, 0x008000, 0x808000, 0x800000,
65 0x800080, 0x408080, 0x404000, 0xff8000, 0x804000, 0xff0040, 0x004080,
66 0xffffff, 0xc0c0c0, 0x0000ff, 0x00ffff, 0x00ff00, 0xffff00, 0xff0000,
67 0xff00ff, 0x80ffff, 0x80ff00, 0xffff80, 0xff8080, 0x8000ff, 0x4080ff
68 };
69
70 /* palette currently in use (1: modern, 2: old) */
71 int selectedPalette;
72
73 /* foreground and background colors with initial value */
74 int fgColor = 0x00000000;
75 int bgColor = 0x00ffffff;
76
77 HWND hStatusBar;
78 HWND hTrackbarZoom;
79 CHOOSECOLOR choosecolor;
80 OPENFILENAME ofn;
81 OPENFILENAME sfn;
82 HICON hNontranspIcon;
83 HICON hTranspIcon;
84
85 HCURSOR hCurFill;
86 HCURSOR hCurColor;
87 HCURSOR hCurZoom;
88 HCURSOR hCurPen;
89 HCURSOR hCurAirbrush;
90
91 HWND hToolBtn[16];
92
93 HINSTANCE hProgInstance;
94
95 TCHAR filename[256];
96 TCHAR filepathname[1000];
97 BOOL isAFile = FALSE;
98 int fileSize;
99 int fileHPPM = 2834;
100 int fileVPPM = 2834;
101 SYSTEMTIME fileTime;
102
103 BOOL showGrid = FALSE;
104 BOOL showMiniature = FALSE;
105
106 CMainWindow mainWindow;
107 CMiniatureWindow miniature;
108 CMainWindow toolBoxContainer;
109 CToolSettingsWindow toolSettingsWindow;
110 CPaletteWindow paletteWindow;
111 CScrollboxWindow scrollboxWindow;
112 CScrollboxWindow scrlClientWindow;
113 CSelectionWindow selectionWindow;
114 CImgAreaWindow imageArea;
115 CSizeboxWindow sizeboxLeftTop;
116 CSizeboxWindow sizeboxCenterTop;
117 CSizeboxWindow sizeboxRightTop;
118 CSizeboxWindow sizeboxLeftCenter;
119 CSizeboxWindow sizeboxRightCenter;
120 CSizeboxWindow sizeboxLeftBottom;
121 CSizeboxWindow sizeboxCenterBottom;
122 CSizeboxWindow sizeboxRightBottom;
123 CTextEditWindow textEditWindow;
124
125 /* entry point */
126
127 int WINAPI
128 _tWinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPTSTR lpszArgument, int nFunsterStil)
129 {
130 HWND hwnd; /* This is the handle for our window */
131 MSG messages; /* Here messages to the application are saved */
132
133 TCHAR progtitle[1000];
134 TCHAR resstr[100];
135 HMENU menu;
136 HWND hToolbar;
137 HIMAGELIST hImageList;
138 HANDLE haccel;
139 HBITMAP tempBm;
140 int i;
141 TCHAR tooltips[16][30];
142 HDC hDC;
143
144 TCHAR *c;
145 TCHAR sfnFilename[1000];
146 TCHAR sfnFiletitle[256];
147 TCHAR sfnFilter[1000];
148 TCHAR ofnFilename[1000];
149 TCHAR ofnFiletitle[256];
150 TCHAR ofnFilter[1000];
151 TCHAR miniaturetitle[100];
152 static int custColors[16] = { 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff,
153 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff
154 };
155
156 /* init font for text tool */
157 lfTextFont.lfHeight = 0;
158 lfTextFont.lfWidth = 0;
159 lfTextFont.lfEscapement = 0;
160 lfTextFont.lfOrientation = 0;
161 lfTextFont.lfWeight = FW_NORMAL;
162 lfTextFont.lfItalic = FALSE;
163 lfTextFont.lfUnderline = FALSE;
164 lfTextFont.lfStrikeOut = FALSE;
165 lfTextFont.lfCharSet = DEFAULT_CHARSET;
166 lfTextFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
167 lfTextFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
168 lfTextFont.lfQuality = DEFAULT_QUALITY;
169 lfTextFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
170 lstrcpy(lfTextFont.lfFaceName, _T(""));
171 hfontTextFont = CreateFontIndirect(&lfTextFont);
172
173 /* init palette */
174 selectedPalette = 1;
175 CopyMemory(palColors, modernPalColors, sizeof(palColors));
176
177 hProgInstance = hThisInstance;
178
179 /* initialize common controls library */
180 InitCommonControls();
181
182 LoadString(hThisInstance, IDS_DEFAULTFILENAME, filename, SIZEOF(filename));
183 LoadString(hThisInstance, IDS_WINDOWTITLE, resstr, SIZEOF(resstr));
184 _stprintf(progtitle, resstr, filename);
185 LoadString(hThisInstance, IDS_MINIATURETITLE, miniaturetitle, SIZEOF(miniaturetitle));
186
187 /* create main window */
188 RECT mainWindowPos = {0, 0, 544, 375}; // FIXME: use equivalent of CW_USEDEFAULT for position
189 hwnd = mainWindow.Create(HWND_DESKTOP, mainWindowPos, progtitle, WS_OVERLAPPEDWINDOW, 0, 0U, NULL);
190
191 RECT miniaturePos = {180, 200, 180 + 120, 200 + 100};
192 miniature.Create(hwnd, miniaturePos, miniaturetitle,
193 WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME, WS_EX_PALETTEWINDOW, 0U, NULL);
194
195 /* loading and setting the window menu from resource */
196 menu = LoadMenu(hThisInstance, MAKEINTRESOURCE(ID_MENU));
197 SetMenu(hwnd, menu);
198 haccel = LoadAccelerators(hThisInstance, MAKEINTRESOURCE(800));
199
200 /* preloading the draw transparent/nontransparent icons for later use */
201 hNontranspIcon =
202 (HICON) LoadImage(hThisInstance, MAKEINTRESOURCE(IDI_NONTRANSPARENT), IMAGE_ICON, 40, 30, LR_DEFAULTCOLOR);
203 hTranspIcon =
204 (HICON) LoadImage(hThisInstance, MAKEINTRESOURCE(IDI_TRANSPARENT), IMAGE_ICON, 40, 30, LR_DEFAULTCOLOR);
205
206 hCurFill = LoadIcon(hThisInstance, MAKEINTRESOURCE(IDC_FILL));
207 hCurColor = LoadIcon(hThisInstance, MAKEINTRESOURCE(IDC_COLOR));
208 hCurZoom = LoadIcon(hThisInstance, MAKEINTRESOURCE(IDC_ZOOM));
209 hCurPen = LoadIcon(hThisInstance, MAKEINTRESOURCE(IDC_PEN));
210 hCurAirbrush = LoadIcon(hThisInstance, MAKEINTRESOURCE(IDC_AIRBRUSH));
211
212 CreateWindowEx(0, _T("STATIC"), _T(""), WS_CHILD | WS_VISIBLE | SS_ETCHEDHORZ, 0, 0, 5000, 2, hwnd, NULL,
213 hThisInstance, NULL);
214
215 RECT toolBoxContainerPos = {2, 2, 2 + 52, 2 + 350};
216 toolBoxContainer.Create(hwnd, toolBoxContainerPos, _T(""), WS_CHILD | WS_VISIBLE, 0, 0U, NULL);
217 /* creating the 16 bitmap radio buttons and setting the bitmap */
218
219
220 /*
221 * FIXME: Unintentionally there is a line above the tool bar (hidden by y-offset).
222 * To prevent cropping of the buttons height has been increased from 200 to 205
223 */
224 hToolbar =
225 CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
226 WS_CHILD | WS_VISIBLE | CCS_NOPARENTALIGN | CCS_VERT | CCS_NORESIZE | TBSTYLE_TOOLTIPS,
227 1, -2, 50, 205, toolBoxContainer.m_hWnd, NULL, hThisInstance, NULL);
228 hImageList = ImageList_Create(16, 16, ILC_COLOR24 | ILC_MASK, 16, 0);
229 SendMessage(hToolbar, TB_SETIMAGELIST, 0, (LPARAM) hImageList);
230 tempBm = (HBITMAP) LoadImage(hThisInstance, MAKEINTRESOURCE(IDB_TOOLBARICONS), IMAGE_BITMAP, 256, 16, 0);
231 ImageList_AddMasked(hImageList, tempBm, 0xff00ff);
232 DeleteObject(tempBm);
233 SendMessage(hToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
234
235 for(i = 0; i < 16; i++)
236 {
237 TBBUTTON tbbutton;
238 int wrapnow = 0;
239
240 if (i % 2 == 1)
241 wrapnow = TBSTATE_WRAP;
242
243 LoadString(hThisInstance, IDS_TOOLTIP1 + i, tooltips[i], 30);
244 ZeroMemory(&tbbutton, sizeof(TBBUTTON));
245 tbbutton.iString = (INT_PTR) tooltips[i];
246 tbbutton.fsStyle = TBSTYLE_CHECKGROUP;
247 tbbutton.fsState = TBSTATE_ENABLED | wrapnow;
248 tbbutton.idCommand = ID_FREESEL + i;
249 tbbutton.iBitmap = i;
250 SendMessage(hToolbar, TB_ADDBUTTONS, 1, (LPARAM) &tbbutton);
251 }
252
253 SendMessage(hToolbar, TB_CHECKBUTTON, ID_PEN, MAKELONG(TRUE, 0));
254 SendMessage(hToolbar, TB_SETMAXTEXTROWS, 0, 0);
255 SendMessage(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(25, 25));
256
257 /* creating the tool settings child window */
258 RECT toolSettingsWindowPos = {5, 208, 5 + 42, 208 + 140};
259 toolSettingsWindow.Create(toolBoxContainer.m_hWnd, toolSettingsWindowPos, _T(""), WS_CHILD | WS_VISIBLE, 0, 0U, NULL);
260 hTrackbarZoom =
261 CreateWindowEx(0, TRACKBAR_CLASS, _T(""), WS_CHILD | TBS_VERT | TBS_AUTOTICKS, 1, 1, 40, 64,
262 toolSettingsWindow.m_hWnd, NULL, hThisInstance, NULL);
263 SendMessage(hTrackbarZoom, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG(0, 6));
264 SendMessage(hTrackbarZoom, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) 3);
265
266 /* creating the palette child window */
267 RECT paletteWindowPos = {56, 9, 56 + 255, 9 + 32};
268 paletteWindow.Create(hwnd, paletteWindowPos, _T(""), WS_CHILD | WS_VISIBLE, 0, 0U, NULL);
269
270 /* creating the scroll box */
271 RECT scrollboxWindowPos = {56, 49, 56 + 472, 49 + 248};
272 scrollboxWindow.Create(hwnd, scrollboxWindowPos, _T(""),
273 WS_CHILD | WS_GROUP | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE, WS_EX_CLIENTEDGE, 0U, NULL);
274
275 /* creating the status bar */
276 hStatusBar =
277 CreateWindowEx(0, STATUSCLASSNAME, _T(""), SBARS_SIZEGRIP | WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, hwnd,
278 NULL, hThisInstance, NULL);
279 SendMessage(hStatusBar, SB_SETMINHEIGHT, 21, 0);
280
281 RECT scrlClientWindowPos = {0, 0, 0 + 500, 0 + 500};
282 scrlClientWindow.Create(scrollboxWindow.m_hWnd, scrlClientWindowPos, _T(""), WS_CHILD | WS_VISIBLE, 0, 0U, NULL);
283
284 /* create selection window (initially hidden) */
285 RECT selectionWindowPos = {350, 0, 350 + 100, 0 + 100};
286 selectionWindow.Create(scrlClientWindow.m_hWnd, selectionWindowPos, _T(""), WS_CHILD | BS_OWNERDRAW, 0, 0U, NULL);
287
288 /* creating the window inside the scroll box, on which the image in hDrawingDC's bitmap is drawn */
289 RECT imageAreaPos = {3, 3, 3 + imgXRes, 3 + imgYRes};
290 imageArea.Create(scrlClientWindow.m_hWnd, imageAreaPos, _T(""), WS_CHILD | WS_VISIBLE, 0, 0U, NULL);
291
292 hDC = imageArea.GetDC();
293 hDrawingDC = CreateCompatibleDC(hDC);
294 hSelDC = CreateCompatibleDC(hDC);
295 imageArea.ReleaseDC(hDC);
296 SelectObject(hDrawingDC, CreatePen(PS_SOLID, 0, fgColor));
297 SelectObject(hDrawingDC, CreateSolidBrush(bgColor));
298
299 hBms[0] = CreateDIBWithProperties(imgXRes, imgYRes);
300 SelectObject(hDrawingDC, hBms[0]);
301 Rectangle(hDrawingDC, 0 - 1, 0 - 1, imgXRes + 1, imgYRes + 1);
302
303 if (lpszArgument[0] != 0)
304 {
305 HBITMAP bmNew = NULL;
306 LoadDIBFromFile(&bmNew, lpszArgument, &fileTime, &fileSize, &fileHPPM, &fileVPPM);
307 if (bmNew != NULL)
308 {
309 TCHAR tempstr[1000];
310 TCHAR resstr[100];
311 TCHAR *temp;
312 insertReversible(bmNew);
313 GetFullPathName(lpszArgument, SIZEOF(filepathname), filepathname, &temp);
314 _tcscpy(filename, temp);
315 LoadString(hProgInstance, IDS_WINDOWTITLE, resstr, SIZEOF(resstr));
316 _stprintf(tempstr, resstr, filename);
317 mainWindow.SetWindowText(tempstr);
318 clearHistory();
319 isAFile = TRUE;
320 }
321 else
322 {
323 exit(0);
324 }
325 }
326
327 /* initializing the CHOOSECOLOR structure for use with ChooseColor */
328 choosecolor.lStructSize = sizeof(CHOOSECOLOR);
329 choosecolor.hwndOwner = hwnd;
330 choosecolor.hInstance = NULL;
331 choosecolor.rgbResult = 0x00ffffff;
332 choosecolor.lpCustColors = (COLORREF*) &custColors;
333 choosecolor.Flags = 0;
334 choosecolor.lCustData = 0;
335 choosecolor.lpfnHook = NULL;
336 choosecolor.lpTemplateName = NULL;
337
338 /* initializing the OPENFILENAME structure for use with GetOpenFileName and GetSaveFileName */
339 CopyMemory(ofnFilename, filename, sizeof(filename));
340 LoadString(hThisInstance, IDS_OPENFILTER, ofnFilter, SIZEOF(ofnFilter));
341 for(c = ofnFilter; *c; c++)
342 if (*c == '\1')
343 *c = '\0';
344 ZeroMemory(&ofn, sizeof(OPENFILENAME));
345 ofn.lStructSize = sizeof(OPENFILENAME);
346 ofn.hwndOwner = hwnd;
347 ofn.hInstance = hThisInstance;
348 ofn.lpstrFilter = ofnFilter;
349 ofn.lpstrFile = ofnFilename;
350 ofn.nMaxFile = SIZEOF(ofnFilename);
351 ofn.lpstrFileTitle = ofnFiletitle;
352 ofn.nMaxFileTitle = SIZEOF(ofnFiletitle);
353 ofn.Flags = OFN_HIDEREADONLY;
354
355 CopyMemory(sfnFilename, filename, sizeof(filename));
356 LoadString(hThisInstance, IDS_SAVEFILTER, sfnFilter, SIZEOF(sfnFilter));
357 for(c = sfnFilter; *c; c++)
358 if (*c == '\1')
359 *c = '\0';
360 ZeroMemory(&sfn, sizeof(OPENFILENAME));
361 sfn.lStructSize = sizeof(OPENFILENAME);
362 sfn.hwndOwner = hwnd;
363 sfn.hInstance = hThisInstance;
364 sfn.lpstrFilter = sfnFilter;
365 sfn.lpstrFile = sfnFilename;
366 sfn.nMaxFile = SIZEOF(sfnFilename);
367 sfn.lpstrFileTitle = sfnFiletitle;
368 sfn.nMaxFileTitle = SIZEOF(sfnFiletitle);
369 sfn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
370
371 /* creating the size boxes */
372 RECT sizeboxPos = {0, 0, 0 + 3, 0 + 3};
373 sizeboxLeftTop.Create(scrlClientWindow.m_hWnd, sizeboxPos, _T(""), WS_CHILD | WS_VISIBLE, 0, 0U, NULL);
374 sizeboxCenterTop.Create(scrlClientWindow.m_hWnd, sizeboxPos, _T(""), WS_CHILD | WS_VISIBLE, 0, 0U, NULL);
375 sizeboxRightTop.Create(scrlClientWindow.m_hWnd, sizeboxPos, _T(""), WS_CHILD | WS_VISIBLE, 0, 0U, NULL);
376 sizeboxLeftCenter.Create(scrlClientWindow.m_hWnd, sizeboxPos, _T(""), WS_CHILD | WS_VISIBLE, 0, 0U, NULL);
377 sizeboxRightCenter.Create(scrlClientWindow.m_hWnd, sizeboxPos, _T(""), WS_CHILD | WS_VISIBLE, 0, 0U, NULL);
378 sizeboxLeftBottom.Create(scrlClientWindow.m_hWnd, sizeboxPos, _T(""), WS_CHILD | WS_VISIBLE, 0, 0U, NULL);
379 sizeboxCenterBottom.Create(scrlClientWindow.m_hWnd, sizeboxPos, _T(""), WS_CHILD | WS_VISIBLE, 0, 0U, NULL);
380 sizeboxRightBottom.Create(scrlClientWindow.m_hWnd, sizeboxPos, _T(""), WS_CHILD | WS_VISIBLE, 0, 0U, NULL);
381 /* placing the size boxes around the image */
382 imageArea.SendMessage(WM_SIZE, 0, 0);
383
384 /* by moving the window, the things in WM_SIZE are done */
385 MoveWindow(hwnd, 100, 100, 600, 450, TRUE);
386
387 /* creating the text editor window for the text tool */
388 RECT textEditWindowPos = {300, 0, 300 + 300, 0 + 200};
389 textEditWindow.Create(hwnd, textEditWindowPos, _T(""), WS_OVERLAPPEDWINDOW, 0, 0U, NULL);
390 /* creating the edit control within the editor window */
391 hwndEditCtl =
392 CreateWindowEx(WS_EX_CLIENTEDGE, _T("EDIT"), _T(""),
393 WS_CHILD | WS_VISIBLE | WS_BORDER | WS_HSCROLL | WS_VSCROLL | ES_MULTILINE | ES_NOHIDESEL | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
394 0, 0, 100, 100, textEditWindow.m_hWnd, NULL, hThisInstance, NULL);
395
396 /* Make the window visible on the screen */
397 ShowWindow (hwnd, nFunsterStil);
398
399 /* inform the system, that the main window accepts dropped files */
400 DragAcceptFiles(hwnd, TRUE);
401
402 /* Run the message loop. It will run until GetMessage() returns 0 */
403 while (GetMessage(&messages, NULL, 0, 0))
404 {
405 TranslateAccelerator(hwnd, (HACCEL) haccel, &messages);
406
407 /* Translate virtual-key messages into character messages */
408 TranslateMessage(&messages);
409 /* Send message to WindowProcedure */
410 DispatchMessage(&messages);
411 }
412
413 /* The program return-value is 0 - The value that PostQuitMessage() gave */
414 return messages.wParam;
415 }