Merge from amd64-branch:
[reactos.git] / rosapps / templates / imagesoft / imgedwnd.c
1 #include "precomp.h"
2
3 static const TCHAR szImageEditWndClass[] = TEXT("ImageSoftEditWndClass");
4
5 #define IMAGE_FRAME_SIZE 1
6
7 static VOID
8 EditWndUpdateScrollInfo(PEDIT_WND_INFO Info)
9 {
10 SCROLLINFO si;
11 RECT rcClient;
12
13 GetClientRect(Info->hSelf,
14 &rcClient);
15
16 si.cbSize = sizeof(si);
17 si.fMask = SIF_PAGE | SIF_RANGE;
18 si.nPage = rcClient.right - (2 * IMAGE_FRAME_SIZE);
19 si.nMin = 0;
20 si.nMax = Info->Width;
21
22 SetScrollInfo(Info->hSelf,
23 SB_HORZ,
24 &si,
25 TRUE);
26
27 si.nPage = rcClient.bottom - (2 * IMAGE_FRAME_SIZE);
28 si.nMax = Info->Height;
29 SetScrollInfo(Info->hSelf,
30 SB_VERT,
31 &si,
32 TRUE);
33 }
34
35
36 static BOOL
37 LoadBlankCanvas(PEDIT_WND_INFO Info)
38 {
39 /* FIXME: convert this to a DIB Section */
40 /* set bitmap dimensions */
41 Info->Width = Info->OpenInfo->New.Width;
42 Info->Height = Info->OpenInfo->New.Height;
43
44 return TRUE;
45 }
46
47 static BOOL
48 LoadDIBImage(PEDIT_WND_INFO Info)
49 {
50 BITMAPFILEHEADER bmfh;
51 HANDLE hFile;
52 BITMAP bitmap;
53 DWORD BytesRead;
54 BOOL bSuccess, bRet = FALSE;
55
56 hFile = CreateFile(Info->OpenInfo->Open.lpImagePath,
57 GENERIC_READ,
58 FILE_SHARE_READ,
59 NULL,
60 OPEN_EXISTING,
61 FILE_FLAG_SEQUENTIAL_SCAN,
62 NULL);
63 if (hFile == INVALID_HANDLE_VALUE)
64 return bRet;
65
66 bSuccess = ReadFile(hFile,
67 &bmfh,
68 sizeof(BITMAPFILEHEADER),
69 &BytesRead,
70 NULL);
71
72 if (bSuccess && (BytesRead == sizeof(BITMAPFILEHEADER))
73 && (bmfh.bfType == *(WORD *)"BM"))
74 {
75 DWORD InfoSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
76
77 Info->pbmi = HeapAlloc(ProcessHeap,
78 0,
79 InfoSize);
80 if (Info->pbmi)
81 {
82 bSuccess = ReadFile(hFile,
83 Info->pbmi,
84 InfoSize,
85 &BytesRead,
86 NULL);
87
88 if (bSuccess && (BytesRead == InfoSize))
89 {
90 Info->hBitmap = CreateDIBSection(NULL,
91 Info->pbmi,
92 DIB_RGB_COLORS,
93 (VOID *)&Info->pBits,
94 NULL,
95 0);
96 if (Info->hBitmap != NULL)
97 {
98 ReadFile(hFile,
99 Info->pBits,
100 bmfh.bfSize - bmfh.bfOffBits,
101 &BytesRead,
102 NULL);
103
104 GetObject(Info->hBitmap,
105 sizeof(BITMAP),
106 &bitmap);
107
108 Info->Width = bitmap.bmWidth;
109 Info->Height = bitmap.bmHeight;
110
111 bRet = TRUE;
112 }
113 }
114 }
115 }
116 else if (!bSuccess)
117 {
118 GetError(0);
119 }
120
121 CloseHandle(hFile);
122
123 return bRet;
124 }
125
126
127 static BOOL
128 InitEditWnd(PEDIT_WND_INFO Info)
129 {
130 //BOOL bRet = FALSE;
131
132 Info->Zoom = 100;
133
134 if (Info->OpenInfo != NULL)
135 {
136 HDC hDC;
137
138 if (Info->hDCMem)
139 {
140 DeleteObject(Info->hDCMem);
141 Info->hDCMem = NULL;
142 }
143
144 hDC = GetDC(Info->hSelf);
145 Info->hDCMem = CreateCompatibleDC(hDC);
146 ReleaseDC(Info->hSelf, hDC);
147
148 if (Info->OpenInfo->CreateNew)
149 {
150 LoadBlankCanvas(Info);
151 }
152 else
153 {
154 LoadDIBImage(Info);
155 }
156
157 Info->OpenInfo = NULL;
158 }
159
160 EditWndUpdateScrollInfo(Info);
161
162 /* Add image editor to the list */
163 Info->Next = Info->MainWnd->ImageEditors;
164 Info->MainWnd->ImageEditors = Info;
165
166 InvalidateRect(Info->hSelf,
167 NULL,
168 TRUE);
169
170 /* FIXME - if returning FALSE, remove the image editor from the list! */
171 return TRUE;
172 }
173
174 static VOID
175 DestroyEditWnd(PEDIT_WND_INFO Info)
176 {
177 PEDIT_WND_INFO *PrevEditor;
178 PEDIT_WND_INFO Editor;
179
180 DeleteDC(Info->hDCMem);
181
182 /* FIXME - free resources and run down editor */
183 HeapFree(ProcessHeap,
184 0,
185 Info->pbmi);
186 HeapFree(ProcessHeap,
187 0,
188 Info->pBits);
189
190 /* Remove the image editor from the list */
191 PrevEditor = &Info->MainWnd->ImageEditors;
192 Editor = Info->MainWnd->ImageEditors;
193 do
194 {
195 if (Editor == Info)
196 {
197 *PrevEditor = Info->Next;
198 break;
199 }
200 PrevEditor = &Editor->Next;
201 Editor = Editor->Next;
202 } while (Editor != NULL);
203 }
204
205 static VOID
206 ImageEditWndRepaint(PEDIT_WND_INFO Info,
207 HDC hDC,
208 LPPAINTSTRUCT lpps)
209 {
210 HBITMAP hOldBitmap;
211
212 if (Info->hBitmap)
213 {
214 hOldBitmap = (HBITMAP) SelectObject(Info->hDCMem,
215 Info->hBitmap);
216
217 BitBlt(hDC,
218 lpps->rcPaint.left,
219 lpps->rcPaint.top,
220 lpps->rcPaint.right - lpps->rcPaint.left,
221 lpps->rcPaint.bottom - lpps->rcPaint.top,
222 Info->hDCMem,
223 lpps->rcPaint.left,
224 lpps->rcPaint.top,
225 SRCCOPY);
226
227 Info->hBitmap = SelectObject(Info->hDCMem, hOldBitmap);
228 }
229 }
230
231 static LRESULT CALLBACK
232 ImageEditWndProc(HWND hwnd,
233 UINT uMsg,
234 WPARAM wParam,
235 LPARAM lParam)
236 {
237 PEDIT_WND_INFO Info;
238 LRESULT Ret = 0;
239 HDC hDC;
240 static INT xMouse, yMouse;
241 static BOOL bLeftButtonDown, bRightButtonDown;
242
243 /* Get the window context */
244 Info = (PEDIT_WND_INFO)GetWindowLongPtr(hwnd,
245 GWLP_USERDATA);
246 if (Info == NULL && uMsg != WM_CREATE)
247 {
248 goto HandleDefaultMessage;
249 }
250
251 switch (uMsg)
252 {
253 case WM_CREATE:
254 {
255 Info = (PEDIT_WND_INFO)(((LPMDICREATESTRUCT)((LPCREATESTRUCT)lParam)->lpCreateParams)->lParam);
256 Info->hSelf = hwnd;
257
258 SetWindowLongPtr(hwnd,
259 GWLP_USERDATA,
260 (LONG_PTR)Info);
261
262 if (!InitEditWnd(Info))
263 {
264 Ret = (LRESULT)-1;
265 break;
266 }
267 break;
268 }
269 /*
270 case WM_ERASEBKGND:
271 if (Info->Width != 0 && Info->Height != 0)
272 {
273 Ret = TRUE;
274 }
275 break;
276 */
277 case WM_LBUTTONDOWN:
278 if (! bRightButtonDown)
279 SetCapture(Info->hSelf);
280
281 bLeftButtonDown = TRUE;
282 xMouse = LOWORD(lParam);
283 yMouse = HIWORD(lParam);
284
285 SetCursor(LoadCursor(hInstance,
286 MAKEINTRESOURCE(IDC_PAINTBRUSHCURSORMOUSEDOWN)));
287 break;
288
289 case WM_LBUTTONUP:
290 if (bLeftButtonDown)
291 SetCapture(NULL);
292
293 bLeftButtonDown = FALSE;
294
295 break;
296
297 case WM_RBUTTONDOWN:
298 if (! bLeftButtonDown)
299 SetCapture(Info->hSelf);
300
301 bRightButtonDown = TRUE;
302 xMouse = LOWORD(lParam);
303 yMouse = HIWORD(lParam);
304
305 SetCursor(LoadCursor(hInstance,
306 MAKEINTRESOURCE(IDC_PAINTBRUSHCURSORMOUSEDOWN)));
307 break;
308
309 case WM_RBUTTONUP:
310 if (bRightButtonDown)
311 SetCapture(NULL);
312
313 bRightButtonDown = FALSE;
314
315 break;
316
317 case WM_MOUSEMOVE:
318 {
319 HPEN hPen, hPenOld;
320
321 if (!bLeftButtonDown && !bRightButtonDown)
322 break;
323
324 hDC = GetDC(Info->hSelf);
325
326 SelectObject(Info->hDCMem,
327 Info->hBitmap);
328
329 if (bLeftButtonDown)
330 hPen = CreatePen(PS_SOLID,
331 3,
332 RGB(0, 0, 0));
333 else
334 hPen = CreatePen(PS_SOLID,
335 3,
336 RGB(255, 255, 255));
337
338 hPenOld = SelectObject(hDC,
339 hPen);
340 SelectObject(Info->hDCMem,
341 hPen);
342
343 MoveToEx(hDC,
344 xMouse,
345 yMouse,
346 NULL);
347
348 MoveToEx(Info->hDCMem,
349 xMouse,
350 yMouse,
351 NULL);
352
353 xMouse = (short)LOWORD(lParam);
354 yMouse = (short)HIWORD(lParam);
355
356 LineTo(hDC,
357 xMouse,
358 yMouse);
359
360 LineTo(Info->hDCMem,
361 xMouse,
362 yMouse);
363
364 SelectObject(hDC,
365 hPenOld);
366 DeleteObject(SelectObject(Info->hDCMem,
367 hPenOld));
368
369 ReleaseDC(Info->hSelf,
370 hDC);
371 }
372 break;
373
374 case WM_PAINT:
375 {
376 if (Info->Width != 0 && Info->Height != 0)
377 {
378 PAINTSTRUCT ps;
379 HDC hDC;
380
381 hDC = BeginPaint(hwnd,
382 &ps);
383 if (hDC != NULL)
384 {
385 ImageEditWndRepaint(Info,
386 hDC,
387 &ps);
388
389 EndPaint(hwnd,
390 &ps);
391 }
392 }
393 break;
394 }
395
396 case WM_SIZE:
397 {
398 EditWndUpdateScrollInfo(Info);
399 goto HandleDefaultMessage;
400 }
401
402 case WM_MENUSELECT:
403 case WM_ENTERMENULOOP:
404 case WM_EXITMENULOOP:
405 /* forward these messages to the main window procedure */
406 Ret = SendMessage(Info->MainWnd->hSelf,
407 uMsg,
408 wParam,
409 lParam);
410 break;
411
412 case WM_MDIACTIVATE:
413 /* Switch the main window context if neccessary */
414 MainWndSwitchEditorContext(Info->MainWnd,
415 (HWND)wParam,
416 (HWND)lParam);
417 break;
418
419 case WM_DESTROY:
420 {
421 DestroyEditWnd(Info);
422
423 HeapFree(ProcessHeap,
424 0,
425 Info);
426 SetWindowLongPtr(hwnd,
427 GWLP_USERDATA,
428 0);
429 break;
430 }
431
432 default:
433 HandleDefaultMessage:
434 Ret = DefMDIChildProc(hwnd,
435 uMsg,
436 wParam,
437 lParam);
438 break;
439 }
440
441 return Ret;
442 }
443
444 VOID
445 SetImageEditorEnvironment(PEDIT_WND_INFO Info,
446 BOOL Setup)
447 {
448 if (Setup)
449 {
450 /* FIXME - setup editor environment (e.g. show toolbars, enable menus etc) */
451 }
452 else
453 {
454 /* FIXME - cleanup editor environment (e.g. hide toolbars, disable menus etc) */
455 }
456 }
457
458 BOOL
459 CreateImageEditWindow(PMAIN_WND_INFO MainWnd,
460 POPEN_IMAGE_EDIT_INFO OpenInfo)
461 {
462 PEDIT_WND_INFO Info;
463 HWND hWndEditor;
464 LONG Width, Height;
465
466 Info = HeapAlloc(ProcessHeap,
467 0,
468 sizeof(EDIT_WND_INFO));
469 if (Info != NULL)
470 {
471 ZeroMemory(Info,
472 sizeof(EDIT_WND_INFO));
473 Info->MainWnd = MainWnd;
474 Info->MdiEditorType = metImageEditor;
475 Info->OpenInfo = OpenInfo;
476
477 if (OpenInfo->CreateNew)
478 {
479 Width = OpenInfo->New.Width;
480 Height = OpenInfo->New.Height;
481 }
482 else
483 {
484 Width = CW_USEDEFAULT;
485 Height = CW_USEDEFAULT;
486 }
487
488 hWndEditor = CreateMDIWindow(szImageEditWndClass,
489 OpenInfo->lpImageName,
490 WS_HSCROLL | WS_VSCROLL | WS_MAXIMIZE,
491 200,
492 200,
493 Width,
494 Height,
495 MainWnd->hMdiClient,
496 hInstance,
497 (LPARAM)Info);
498
499 if (hWndEditor != NULL)
500 {
501 return TRUE;
502 }
503
504 HeapFree(ProcessHeap,
505 0,
506 Info);
507 }
508
509 return FALSE;
510 }
511
512 BOOL
513 InitImageEditWindowImpl(VOID)
514 {
515 WNDCLASSEX wc = {0};
516
517 wc.cbSize = sizeof(WNDCLASSEX);
518 wc.style = CS_HREDRAW | CS_VREDRAW;
519 wc.lpfnWndProc = ImageEditWndProc;
520 wc.hInstance = hInstance;
521 wc.hIcon = LoadIcon(hInstance,
522 MAKEINTRESOURCE(IDI_IMAGESOFTICON));
523 wc.hCursor = LoadCursor(hInstance,
524 MAKEINTRESOURCE(IDC_PAINTBRUSHCURSOR));
525 wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
526 wc.lpszClassName = szImageEditWndClass;
527 wc.hIconSm = (HICON)LoadImage(hInstance,
528 MAKEINTRESOURCE(IDI_IMAGESOFTICON),
529 IMAGE_ICON,
530 16,
531 16,
532 LR_SHARED);
533
534 return RegisterClassEx(&wc) != (ATOM)0;
535 }
536
537 VOID
538 UninitImageEditWindowImpl(VOID)
539 {
540 UnregisterClass(szImageEditWndClass,
541 hInstance);
542 }