[PAINT]
[reactos.git] / reactos / base / applications / paint / main.c
1 /*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL
4 * FILE: main.c
5 * PURPOSE: Initializing everything
6 * PROGRAMMERS: Benedikt Freisen
7 */
8
9 /* INCLUDES *********************************************************/
10
11 #include <windows.h>
12 #include <windowsx.h>
13 #include <commctrl.h>
14 #include <stdio.h>
15 #include <tchar.h>
16 #include "definitions.h"
17
18 #include "drawing.h"
19 #include "dib.h"
20
21 #include "globalvar.h"
22 #include "history.h"
23 #include "mouse.h"
24
25 #include "winproc.h"
26 #include "palette.h"
27 #include "toolsettings.h"
28 #include "selection.h"
29 #include "sizebox.h"
30
31 /* FUNCTIONS ********************************************************/
32
33 HDC hDrawingDC;
34 HDC hSelDC;
35 int *bmAddress;
36 BITMAPINFO bitmapinfo;
37 int imgXRes = 400;
38 int imgYRes = 300;
39
40 HBITMAP hBms[HISTORYSIZE];
41 int currInd = 0;
42 int undoSteps = 0;
43 int redoSteps = 0;
44 BOOL imageSaved = TRUE;
45
46 // global status variables
47
48 short startX;
49 short startY;
50 short lastX;
51 short lastY;
52 int lineWidth = 1;
53 int shapeStyle = 0;
54 int brushStyle = 0;
55 int activeTool = 7;
56 int airBrushWidth = 5;
57 int rubberRadius = 4;
58 int transpBg = 0;
59 int zoom = 1000;
60 int rectSel_src[4];
61 int rectSel_dest[4];
62 HWND hSelection;
63 HWND hImageArea;
64 HBITMAP hSelBm;
65
66
67 // global declarations and WinMain
68
69
70 // initial palette colors; may be changed by the user during execution
71 int palColors[28] =
72 {0x000000, 0x464646, 0x787878, 0x300099, 0x241ced, 0x0078ff, 0x0ec2ff,
73 0x00f2ff, 0x1de6a8, 0x4cb122, 0xefb700, 0xf36d4d, 0x99362f, 0x98316f,
74 0xffffff, 0xdcdcdc, 0xb4b4b4, 0x3c5a9c, 0xb1a3ff, 0x7aaae5, 0x9ce4f5,
75 0xbdf9ff, 0xbcf9d3, 0x61bb9d, 0xead999, 0xd19a70, 0x8e6d54, 0xd5a5b5};
76 // foreground and background colors with initial value
77 int fgColor = 0x00000000;
78 int bgColor = 0x00ffffff;
79 // the current zoom in percent*10
80 HWND hStatusBar;
81 HWND hScrollbox;
82 HWND hMainWnd;
83 HWND hPalWin;
84 HWND hToolSettings;
85 CHOOSECOLOR choosecolor;
86 OPENFILENAME ofn;
87 OPENFILENAME sfn;
88 HICON hNontranspIcon;
89 HICON hTranspIcon;
90
91 HCURSOR hCurFill;
92 HCURSOR hCurColor;
93 HCURSOR hCurZoom;
94 HCURSOR hCurPen;
95 HCURSOR hCurAirbrush;
96
97 HWND hScrlClient;
98
99 HWND hToolBtn[16];
100
101 HINSTANCE hProgInstance;
102
103 TCHAR filename[256];
104 TCHAR filepathname[1000];
105 BOOL isAFile = FALSE;
106 int fileSize;
107 int fileHPPM = 2834;
108 int fileVPPM = 2834;
109 SYSTEMTIME fileTime;
110
111 BOOL showGrid = FALSE;
112 BOOL showMiniature = FALSE;
113
114 HWND hwndMiniature;
115
116 HWND hSizeboxLeftTop;
117 HWND hSizeboxCenterTop;
118 HWND hSizeboxRightTop;
119 HWND hSizeboxLeftCenter;
120 HWND hSizeboxRightCenter;
121 HWND hSizeboxLeftBottom;
122 HWND hSizeboxCenterBottom;
123 HWND hSizeboxRightBottom;
124
125 HWND hTrackbarZoom;
126
127 int WINAPI _tWinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPTSTR lpszArgument, int nFunsterStil)
128 {
129 HWND hwnd; /* This is the handle for our window */
130 MSG messages; /* Here messages to the application are saved */
131 WNDCLASSEX wclScroll;
132 WNDCLASSEX wincl;
133 WNDCLASSEX wclPal;
134 WNDCLASSEX wclSettings;
135 WNDCLASSEX wclSelection;
136 TCHAR progtitle[1000];
137 TCHAR resstr[100];
138 HMENU menu;
139 HWND hToolbar;
140 HIMAGELIST hImageList;
141 HANDLE haccel;
142 HBITMAP tempBm;
143 int i;
144 TCHAR tooltips[16][30];
145 TCHAR *c;
146 TCHAR sfnFilename[1000];
147 TCHAR sfnFiletitle[256];
148 TCHAR sfnFilter[1000];
149 TCHAR ofnFilename[1000];
150 TCHAR ofnFiletitle[256];
151 TCHAR ofnFilter[1000];
152 TCHAR miniaturetitle[100];
153 int custColors[16] =
154 {0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff,
155 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff};
156
157 hProgInstance = hThisInstance;
158
159 /* Necessary */
160 InitCommonControls();
161
162 /* initializing and registering the window class used for the main window */
163 wincl.hInstance = hThisInstance;
164 wincl.lpszClassName = _T("WindowsApp");
165 wincl.lpfnWndProc = WindowProcedure;
166 wincl.style = CS_DBLCLKS;
167 wincl.cbSize = sizeof (WNDCLASSEX);
168 wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
169 wincl.hIconSm = LoadIcon (hThisInstance, MAKEINTRESOURCE(500));
170 wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
171 wincl.lpszMenuName = NULL;
172 wincl.cbClsExtra = 0;
173 wincl.cbWndExtra = 0;
174 wincl.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
175 RegisterClassEx (&wincl);
176
177 /* initializing and registering the window class used for the scroll box */
178 wclScroll.hInstance = hThisInstance;
179 wclScroll.lpszClassName = _T("Scrollbox");
180 wclScroll.lpfnWndProc = WindowProcedure;
181 wclScroll.style = 0;
182 wclScroll.cbSize = sizeof (WNDCLASSEX);
183 wclScroll.hIcon = NULL;
184 wclScroll.hIconSm = NULL;
185 wclScroll.hCursor = LoadCursor (NULL, IDC_ARROW);
186 wclScroll.lpszMenuName = NULL;
187 wclScroll.cbClsExtra = 0;
188 wclScroll.cbWndExtra = 0;
189 wclScroll.hbrBackground = GetSysColorBrush(COLOR_APPWORKSPACE);
190 RegisterClassEx (&wclScroll);
191
192 /* initializing and registering the window class used for the palette window */
193 wclPal.hInstance = hThisInstance;
194 wclPal.lpszClassName = _T("Palette");
195 wclPal.lpfnWndProc = PalWinProc;
196 wclPal.style = CS_DBLCLKS;
197 wclPal.cbSize = sizeof (WNDCLASSEX);
198 wclPal.hIcon = NULL;
199 wclPal.hIconSm = NULL;
200 wclPal.hCursor = LoadCursor (NULL, IDC_ARROW);
201 wclPal.lpszMenuName = NULL;
202 wclPal.cbClsExtra = 0;
203 wclPal.cbWndExtra = 0;
204 wclPal.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
205 RegisterClassEx (&wclPal);
206
207 /* initializing and registering the window class for the settings window */
208 wclSettings.hInstance = hThisInstance;
209 wclSettings.lpszClassName = _T("ToolSettings");
210 wclSettings.lpfnWndProc = SettingsWinProc;
211 wclSettings.style = CS_DBLCLKS;
212 wclSettings.cbSize = sizeof (WNDCLASSEX);
213 wclSettings.hIcon = NULL;
214 wclSettings.hIconSm = NULL;
215 wclSettings.hCursor = LoadCursor (NULL, IDC_ARROW);
216 wclSettings.lpszMenuName = NULL;
217 wclSettings.cbClsExtra = 0;
218 wclSettings.cbWndExtra = 0;
219 wclSettings.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
220 RegisterClassEx (&wclSettings);
221
222 /* initializing and registering the window class for the selection frame */
223 wclSelection.hInstance = hThisInstance;
224 wclSelection.lpszClassName = _T("Selection");
225 wclSelection.lpfnWndProc = SelectionWinProc;
226 wclSelection.style = CS_DBLCLKS;
227 wclSelection.cbSize = sizeof (WNDCLASSEX);
228 wclSelection.hIcon = NULL;
229 wclSelection.hIconSm = NULL;
230 wclSelection.hCursor = LoadCursor (NULL, IDC_SIZEALL);
231 wclSelection.lpszMenuName = NULL;
232 wclSelection.cbClsExtra = 0;
233 wclSelection.cbWndExtra = 0;
234 wclSelection.hbrBackground = NULL;//GetSysColorBrush(COLOR_BTNFACE);
235 RegisterClassEx (&wclSelection);
236
237 /* initializing and registering the window class for the size boxes */
238 wclSettings.hInstance = hThisInstance;
239 wclSettings.lpszClassName = _T("Sizebox");
240 wclSettings.lpfnWndProc = SizeboxWinProc;
241 wclSettings.style = CS_DBLCLKS;
242 wclSettings.cbSize = sizeof (WNDCLASSEX);
243 wclSettings.hIcon = NULL;
244 wclSettings.hIconSm = NULL;
245 wclSettings.hCursor = LoadCursor (NULL, IDC_ARROW);
246 wclSettings.lpszMenuName = NULL;
247 wclSettings.cbClsExtra = 0;
248 wclSettings.cbWndExtra = 0;
249 wclSettings.hbrBackground = GetSysColorBrush(COLOR_HIGHLIGHT);
250 RegisterClassEx (&wclSettings);
251
252 LoadString(hThisInstance, IDS_DEFAULTFILENAME, filename, SIZEOF(filename));
253 LoadString(hThisInstance, IDS_WINDOWTITLE, resstr, SIZEOF(resstr));
254 _stprintf(progtitle, resstr, filename);
255 LoadString(hThisInstance, IDS_MINIATURETITLE, miniaturetitle, SIZEOF(miniaturetitle));
256
257 /* create main window */
258 hwnd = CreateWindowEx (0, _T("WindowsApp"), progtitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 544, 375, HWND_DESKTOP, NULL, hThisInstance, NULL);
259
260 hMainWnd = hwnd;
261 hwndMiniature = CreateWindowEx(WS_EX_PALETTEWINDOW, _T("WindowsApp"), miniaturetitle, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME, 180, 200, 120, 100, hwnd, NULL, hThisInstance, NULL);
262
263 /* loading and setting the window menu from resource */
264 menu = LoadMenu(hThisInstance, MAKEINTRESOURCE(ID_MENU));
265 SetMenu(hwnd, menu);
266 haccel = LoadAccelerators(hThisInstance, MAKEINTRESOURCE(800));
267
268 /* preloading the draw transparent/nontransparent icons for later use */
269 hNontranspIcon = LoadImage(hThisInstance, MAKEINTRESOURCE(IDI_NONTRANSPARENT), IMAGE_ICON, 40, 30, LR_DEFAULTCOLOR);
270 hTranspIcon = LoadImage(hThisInstance, MAKEINTRESOURCE(IDI_TRANSPARENT), IMAGE_ICON, 40, 30, LR_DEFAULTCOLOR);
271
272 hCurFill = LoadIcon(hThisInstance, MAKEINTRESOURCE(IDC_FILL));
273 hCurColor = LoadIcon(hThisInstance, MAKEINTRESOURCE(IDC_COLOR));
274 hCurZoom = LoadIcon(hThisInstance, MAKEINTRESOURCE(IDC_ZOOM));
275 hCurPen = LoadIcon(hThisInstance, MAKEINTRESOURCE(IDC_PEN));
276 hCurAirbrush = LoadIcon(hThisInstance, MAKEINTRESOURCE(IDC_AIRBRUSH));
277
278 CreateWindowEx (0, _T("STATIC"), _T(""), WS_CHILD | WS_VISIBLE | SS_ETCHEDHORZ, 0, 0, 5000, 2, hwnd, NULL, hThisInstance, NULL);
279
280 /* creating the 16 bitmap radio buttons and setting the bitmap */
281
282
283 /* FIXME: Unintentionally there is a line above the tool bar. To prevent cropping of the buttons height has been increased from 200 to 205 */
284 hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | CCS_NOPARENTALIGN | CCS_VERT | CCS_NORESIZE | TBSTYLE_TOOLTIPS, 3, 3, 50, 205, hwnd, NULL, hThisInstance, NULL);
285 hImageList = ImageList_Create(16, 16, ILC_COLOR24 | ILC_MASK, 16, 0);
286 SendMessage(hToolbar, TB_SETIMAGELIST, 0, (LPARAM)hImageList);
287 tempBm = LoadImage(hThisInstance, MAKEINTRESOURCE(IDB_TOOLBARICONS), IMAGE_BITMAP, 256, 16, 0);
288 ImageList_AddMasked(hImageList, tempBm, 0xff00ff);
289 DeleteObject(tempBm);
290 SendMessage(hToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
291 for (i=0; i<16; i++)
292 {
293 TBBUTTON tbbutton;
294 int wrapnow = 0;
295
296 if (i % 2 == 1) wrapnow = TBSTATE_WRAP;
297 LoadString(hThisInstance, IDS_TOOLTIP1 + i, tooltips[i], 30);
298 ZeroMemory(&tbbutton, sizeof(TBBUTTON));
299 tbbutton.iString = (INT_PTR)tooltips[i];
300 tbbutton.fsStyle = TBSTYLE_CHECKGROUP;
301 tbbutton.fsState = TBSTATE_ENABLED | wrapnow;
302 tbbutton.idCommand = ID_FREESEL + i;
303 tbbutton.iBitmap = i;
304 SendMessage(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&tbbutton);
305 }
306 /* SendMessage(hToolbar, TB_SETROWS, MAKEWPARAM(8, FALSE), (LPARAM)NULL); */
307 SendMessage(hToolbar, TB_CHECKBUTTON, ID_PEN, MAKELONG(TRUE, 0));
308 SendMessage(hToolbar, TB_SETMAXTEXTROWS, 0, 0);
309
310 SendMessage(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(25, 25));
311 /* SendMessage(hToolbar, TB_AUTOSIZE, 0, 0); */
312
313 /* creating the tool settings child window */
314 hToolSettings = CreateWindowEx(0, _T("ToolSettings"), _T(""), WS_CHILD | WS_VISIBLE, 7, 210, 42, 140, hwnd, NULL, hThisInstance, NULL);
315 hTrackbarZoom = CreateWindowEx(0, TRACKBAR_CLASS, _T(""), WS_CHILD | TBS_VERT | TBS_AUTOTICKS, 1, 1, 40, 64, hToolSettings, NULL, hThisInstance, NULL);
316 SendMessage(hTrackbarZoom, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 6));
317 SendMessage(hTrackbarZoom, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)3);
318
319 /* creating the palette child window */
320 hPalWin = CreateWindowEx(0, _T("Palette"), _T(""), WS_CHILD | WS_VISIBLE, 56, 9, 255, 32, hwnd, NULL, hThisInstance, NULL);
321
322 /* creating the scroll box */
323 hScrollbox = CreateWindowEx (WS_EX_CLIENTEDGE, _T("Scrollbox"), _T(""), WS_CHILD | WS_GROUP | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE, 56, 49, 472, 248, hwnd, NULL, hThisInstance, NULL);
324
325 /* creating the status bar */
326 hStatusBar = CreateWindowEx (0, STATUSCLASSNAME, _T(""), SBARS_SIZEGRIP | WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, hwnd, NULL, hThisInstance, NULL);
327 SendMessage(hStatusBar, SB_SETMINHEIGHT, 21, 0);
328
329 hScrlClient = CreateWindowEx(0, _T("Scrollbox"), _T(""), WS_CHILD | WS_VISIBLE, 0, 0, 500, 500, hScrollbox, NULL, hThisInstance, NULL);
330
331 /* create selection window (initially hidden) */
332 hSelection = CreateWindowEx(WS_EX_TRANSPARENT, _T("Selection"), _T(""), WS_CHILD | BS_OWNERDRAW, 350, 0, 100, 100, hScrlClient, NULL, hThisInstance, NULL);
333
334 /* creating the window inside the scroll box, on which the image in hDrawingDC's bitmap is drawn */
335 hImageArea = CreateWindowEx (0, _T("Scrollbox"), _T(""), WS_CHILD | WS_VISIBLE, 3, 3, imgXRes, imgYRes, hScrlClient, NULL, hThisInstance, NULL);
336
337 hDrawingDC = CreateCompatibleDC(GetDC(hImageArea));
338 hSelDC = CreateCompatibleDC(GetDC(hImageArea));
339 SelectObject(hDrawingDC, CreatePen(PS_SOLID, 0, fgColor));
340 SelectObject(hDrawingDC, CreateSolidBrush(bgColor));
341
342 hBms[0] = CreateDIBWithProperties(imgXRes, imgYRes);
343 SelectObject(hDrawingDC, hBms[0]);
344 Rectangle(hDrawingDC, 0-1, 0-1, imgXRes+1, imgYRes+1);
345
346 if (lpszArgument[0] != 0)
347 {
348 HBITMAP bmNew = NULL;
349 LoadDIBFromFile(&bmNew, lpszArgument, &fileTime, &fileSize, &fileHPPM, &fileVPPM);
350 if (bmNew!=NULL)
351 {
352 TCHAR tempstr[1000];
353 TCHAR resstr[100];
354 insertReversible(bmNew);
355 TCHAR *temp;
356 GetFullPathName(lpszArgument, sizeof(filepathname), filepathname, &temp);
357 _tcscpy(filename, temp);
358 LoadString(hProgInstance, IDS_WINDOWTITLE, resstr, SIZEOF(resstr));
359 _stprintf(tempstr, resstr, filename);
360 SetWindowText(hMainWnd, tempstr);
361 clearHistory();
362 isAFile = TRUE;
363 }
364 }
365
366 /* initializing the CHOOSECOLOR structure for use with ChooseColor */
367 choosecolor.lStructSize = sizeof(CHOOSECOLOR);
368 choosecolor.hwndOwner = hwnd;
369 choosecolor.hInstance = NULL;
370 choosecolor.rgbResult = 0x00ffffff;
371 choosecolor.lpCustColors = (COLORREF*)&custColors;
372 choosecolor.Flags = 0;
373 choosecolor.lCustData = 0;
374 choosecolor.lpfnHook = NULL;
375 choosecolor.lpTemplateName = NULL;
376
377 /* initializing the OPENFILENAME structure for use with GetOpenFileName and GetSaveFileName */
378 CopyMemory(ofnFilename, filename, sizeof(filename));
379 LoadString(hThisInstance, IDS_OPENFILTER, ofnFilter, SIZEOF(ofnFilter));
380 for (c = ofnFilter; *c; c++) if (*c == '\1') *c = '\0';
381 ZeroMemory(&ofn, sizeof(OPENFILENAME));
382 ofn.lStructSize = sizeof (OPENFILENAME);
383 ofn.hwndOwner = hwnd;
384 ofn.hInstance = hThisInstance;
385 ofn.lpstrFilter = ofnFilter;
386 ofn.lpstrFile = ofnFilename;
387 ofn.nMaxFile = SIZEOF(ofnFilename);
388 ofn.lpstrFileTitle = ofnFiletitle;
389 ofn.nMaxFileTitle = SIZEOF(ofnFiletitle);
390 ofn.Flags = OFN_HIDEREADONLY;
391
392 CopyMemory(sfnFilename, filename, sizeof(filename));
393 LoadString(hThisInstance, IDS_SAVEFILTER, sfnFilter, SIZEOF(sfnFilter));
394 for (c = sfnFilter; *c; c++) if (*c == '\1') *c = '\0';
395 ZeroMemory(&sfn, sizeof(OPENFILENAME));
396 sfn.lStructSize = sizeof (OPENFILENAME);
397 sfn.hwndOwner = hwnd;
398 sfn.hInstance = hThisInstance;
399 sfn.lpstrFilter = sfnFilter;
400 sfn.lpstrFile = sfnFilename;
401 sfn.nMaxFile = SIZEOF(sfnFilename);
402 sfn.lpstrFileTitle = sfnFiletitle;
403 sfn.nMaxFileTitle = SIZEOF(sfnFiletitle);
404 sfn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
405
406 hSizeboxLeftTop = CreateWindowEx(0, _T("Sizebox"), _T(""), WS_CHILD | WS_VISIBLE, 0, 0, 3, 3, hScrlClient, NULL, hThisInstance, NULL);
407 hSizeboxCenterTop = CreateWindowEx(0, _T("Sizebox"), _T(""), WS_CHILD | WS_VISIBLE, 0, 0, 3, 3, hScrlClient, NULL, hThisInstance, NULL);
408 hSizeboxRightTop = CreateWindowEx(0, _T("Sizebox"), _T(""), WS_CHILD | WS_VISIBLE, 0, 0, 3, 3, hScrlClient, NULL, hThisInstance, NULL);
409 hSizeboxLeftCenter = CreateWindowEx(0, _T("Sizebox"), _T(""), WS_CHILD | WS_VISIBLE, 0, 0, 3, 3, hScrlClient, NULL, hThisInstance, NULL);
410 hSizeboxRightCenter = CreateWindowEx(0, _T("Sizebox"), _T(""), WS_CHILD | WS_VISIBLE, 0, 0, 3, 3, hScrlClient, NULL, hThisInstance, NULL);
411 hSizeboxLeftBottom = CreateWindowEx(0, _T("Sizebox"), _T(""), WS_CHILD | WS_VISIBLE, 0, 0, 3, 3, hScrlClient, NULL, hThisInstance, NULL);
412 hSizeboxCenterBottom= CreateWindowEx(0, _T("Sizebox"), _T(""), WS_CHILD | WS_VISIBLE, 0, 0, 3, 3, hScrlClient, NULL, hThisInstance, NULL);
413 hSizeboxRightBottom = CreateWindowEx(0, _T("Sizebox"), _T(""), WS_CHILD | WS_VISIBLE, 0, 0, 3, 3, hScrlClient, NULL, hThisInstance, NULL);
414 SendMessage(hImageArea, WM_SIZE, 0, 0);
415
416 /* by moving the window, the things in WM_SIZE are done */
417 MoveWindow(hwnd, 100, 100, 600, 450, TRUE);
418
419 /* Make the window visible on the screen */
420 ShowWindow (hwnd, nFunsterStil);
421
422 /* Run the message loop. It will run until GetMessage() returns 0 */
423 while (GetMessage (&messages, NULL, 0, 0))
424 {
425 TranslateAccelerator(hwnd, haccel, &messages);
426
427 /* Translate virtual-key messages into character messages */
428 TranslateMessage(&messages);
429 /* Send message to WindowProcedure */
430 DispatchMessage(&messages);
431 }
432
433 /* The program return-value is 0 - The value that PostQuitMessage() gave */
434 return messages.wParam;
435 }