Revert an unwanted change from r66575.
[reactos.git] / reactos / base / shell / shimgvw / shimgvw.c
1 /*
2 *
3 * PROJECT: ReactOS Picture and Fax Viewer
4 * FILE: dll/win32/shimgvw/shimgvw.c
5 * PURPOSE: shimgvw.dll
6 * PROGRAMMER: Dmitry Chapyshev (dmitry@reactos.org)
7 *
8 * UPDATE HISTORY:
9 * 28/05/2008 Created
10 */
11
12 #define WIN32_NO_STATUS
13 #define _INC_WINDOWS
14 #define COM_NO_WINDOWS_H
15
16 #include <stdarg.h>
17
18 #include <windef.h>
19 #include <winbase.h>
20 #include <winnls.h>
21 #include <winreg.h>
22 #include <wingdi.h>
23 #include <objbase.h>
24 #include <commctrl.h>
25 #include <commdlg.h>
26 #include <gdiplus.h>
27 #include <tchar.h>
28 #include <strsafe.h>
29 #include <shlwapi.h>
30
31 #define NDEBUG
32 #include <debug.h>
33
34 #include "shimgvw.h"
35
36
37 HINSTANCE hInstance;
38 SHIMGVW_SETTINGS shiSettings;
39 SHIMGVW_FILENODE *currentFile;
40 GpImage *image;
41 WNDPROC PrevProc = NULL;
42
43 HWND hDispWnd, hToolBar;
44
45 /* ToolBar Buttons */
46 static const TBBUTTON Buttons [] =
47 { /* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */
48 {TBICON_PREV, IDC_PREV, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0},
49 {TBICON_NEXT, IDC_NEXT, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0},
50 {15, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0},
51 {TBICON_ZOOMP, IDC_ZOOMP, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0},
52 {TBICON_ZOOMM, IDC_ZOOMM, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0},
53 {15, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0},
54 {TBICON_ROT1, IDC_ROT1, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0},
55 {TBICON_ROT2, IDC_ROT2, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0},
56 {15, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0},
57 {TBICON_SAVE, IDC_SAVE, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0},
58 {TBICON_PRINT, IDC_PRINT, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0},
59 };
60
61 static void pLoadImage(LPWSTR szOpenFileName)
62 {
63 if (GetFileAttributesW(szOpenFileName) == 0xFFFFFFFF)
64 {
65 DPRINT1("File %s not found!\n", szOpenFileName);
66 return;
67 }
68
69 GdipLoadImageFromFile(szOpenFileName, &image);
70 if (!image)
71 {
72 DPRINT1("GdipLoadImageFromFile() failed\n");
73 }
74 }
75
76 static void pSaveImageAs(HWND hwnd)
77 {
78 OPENFILENAMEW sfn;
79 ImageCodecInfo *codecInfo;
80 WCHAR szSaveFileName[MAX_PATH];
81 WCHAR *szFilterMask;
82 GUID rawFormat;
83 UINT num;
84 UINT size;
85 UINT sizeRemain;
86 UINT j;
87 WCHAR *c;
88
89 GdipGetImageEncodersSize(&num, &size);
90 codecInfo = malloc(size);
91 if (!codecInfo)
92 {
93 DPRINT1("malloc() failed in pSaveImageAs()\n");
94 return;
95 }
96
97 GdipGetImageEncoders(num, size, codecInfo);
98 GdipGetImageRawFormat(image, &rawFormat);
99
100 sizeRemain = 0;
101
102 for (j = 0; j < num; ++j)
103 {
104 // Every pair needs space for the Description, twice the Extensions, 1 char for the space, 2 for the braces and 2 for the NULL terminators.
105 sizeRemain = sizeRemain + (((wcslen(codecInfo[j].FormatDescription) + (wcslen(codecInfo[j].FilenameExtension) * 2) + 5) * sizeof(WCHAR)));
106 }
107
108 /* Add two more chars for the last terminator */
109 sizeRemain = sizeRemain + (sizeof(WCHAR) * 2);
110
111 szFilterMask = malloc(sizeRemain);
112 if (!szFilterMask)
113 {
114 DPRINT1("cannot allocate memory for filter mask in pSaveImageAs()");
115 free(codecInfo);
116 return;
117 }
118
119 ZeroMemory(szSaveFileName, sizeof(szSaveFileName));
120 ZeroMemory(szFilterMask, sizeRemain);
121 ZeroMemory(&sfn, sizeof(sfn));
122 sfn.lStructSize = sizeof(sfn);
123 sfn.hwndOwner = hwnd;
124 sfn.hInstance = hInstance;
125 sfn.lpstrFile = szSaveFileName;
126 sfn.lpstrFilter = szFilterMask;
127 sfn.nMaxFile = MAX_PATH;
128 sfn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
129
130 c = szFilterMask;
131
132 for (j = 0; j < num; ++j)
133 {
134 StringCbPrintfExW(c, sizeRemain, &c, &sizeRemain, 0, L"%ls (%ls)", codecInfo[j].FormatDescription, codecInfo[j].FilenameExtension);
135
136 /* Skip the NULL character */
137 c++;
138 sizeRemain -= sizeof(*c);
139
140 StringCbPrintfExW(c, sizeRemain, &c, &sizeRemain, 0, L"%ls", codecInfo[j].FilenameExtension);
141
142 /* Skip the NULL character */
143 c++;
144 sizeRemain -= sizeof(*c);
145
146 if (IsEqualGUID(&rawFormat, &codecInfo[j].FormatID) == TRUE)
147 {
148 sfn.nFilterIndex = j + 1;
149 }
150 }
151
152 if (GetSaveFileNameW(&sfn))
153 {
154 if (GdipSaveImageToFile(image, szSaveFileName, &codecInfo[sfn.nFilterIndex - 1].Clsid, NULL) != Ok)
155 {
156 DPRINT1("GdipSaveImageToFile() failed\n");
157 }
158 }
159
160 free(szFilterMask);
161 free(codecInfo);
162 }
163
164 static VOID
165 pLoadImageFromNode(SHIMGVW_FILENODE *node, HWND hwnd)
166 {
167 WCHAR szTitleBuf[800];
168 WCHAR szResStr[512];
169 WCHAR *c;
170
171 if (node)
172 {
173 c = wcsrchr(node->FileName, '\\');
174 if (c)
175 {
176 c++;
177 }
178
179 LoadStringW(hInstance, IDS_APPTITLE, szResStr, 512);
180 StringCbPrintfExW(szTitleBuf, 800, NULL, NULL, 0, L"%ls%ls%ls", szResStr, L" - ", c);
181 SetWindowTextW(hwnd, szTitleBuf);
182
183 if (image)
184 {
185 GdipDisposeImage(image);
186 }
187
188 pLoadImage(node->FileName);
189 InvalidateRect(hDispWnd, NULL, TRUE);
190 UpdateWindow(hDispWnd);
191 }
192 }
193
194 static SHIMGVW_FILENODE*
195 pBuildFileList(LPWSTR szFirstFile)
196 {
197 HANDLE hFindHandle;
198 WCHAR *extension;
199 WCHAR szSearchPath[MAX_PATH];
200 WCHAR szSearchMask[MAX_PATH];
201 WCHAR szFileTypes[MAX_PATH];
202 WIN32_FIND_DATAW findData;
203 SHIMGVW_FILENODE *currentNode;
204 SHIMGVW_FILENODE *root;
205 SHIMGVW_FILENODE *conductor;
206 ImageCodecInfo *codecInfo;
207 UINT num;
208 UINT size;
209 UINT j;
210
211
212 wcscpy(szSearchPath, szFirstFile);
213 PathRemoveFileSpecW(szSearchPath);
214
215 GdipGetImageDecodersSize(&num, &size);
216 codecInfo = malloc(size);
217 if (!codecInfo)
218 {
219 DPRINT1("malloc() failed in pLoadFileList()\n");
220 return NULL;
221 }
222
223 GdipGetImageDecoders(num, size, codecInfo);
224
225 root = malloc(sizeof(SHIMGVW_FILENODE));
226 if (!root)
227 {
228 DPRINT1("malloc() failed in pLoadFileList()\n");
229 free(codecInfo);
230 return NULL;
231 }
232
233 conductor = root;
234
235 for (j = 0; j < num; ++j)
236 {
237 StringCbPrintfExW(szFileTypes, MAX_PATH, NULL, NULL, 0, L"%ls", codecInfo[j].FilenameExtension);
238
239 extension = wcstok(szFileTypes, L";");
240 while (extension != NULL)
241 {
242 StringCbPrintfExW(szSearchMask, MAX_PATH, NULL, NULL, 0, L"%ls%ls%ls", szSearchPath, L"\\", extension);
243
244 hFindHandle = FindFirstFileW(szSearchMask, &findData);
245 if (hFindHandle != INVALID_HANDLE_VALUE)
246 {
247 do
248 {
249 StringCbPrintfExW(conductor->FileName, MAX_PATH, NULL, NULL, 0, L"%ls%ls%ls", szSearchPath, L"\\", findData.cFileName);
250
251 // compare the name of the requested file with the one currently found.
252 // if the name matches, the current node is returned by the function.
253 if (wcscmp(szFirstFile, conductor->FileName) == 0)
254 {
255 currentNode = conductor;
256 }
257
258 conductor->Next = malloc(sizeof(SHIMGVW_FILENODE));
259
260 // if malloc fails, make circular what we have and return it
261 if (!conductor->Next)
262 {
263 DPRINT1("malloc() failed in pLoadFileList()\n");
264
265 conductor->Next = root;
266 root->Prev = conductor;
267
268 FindClose(hFindHandle);
269 free(codecInfo);
270 return conductor;
271 }
272
273 conductor->Next->Prev = conductor;
274 conductor = conductor->Next;
275 }
276 while (FindNextFileW(hFindHandle, &findData) != 0);
277
278 FindClose(hFindHandle);
279 }
280
281 extension = wcstok(NULL, L";");
282 }
283 }
284
285 // we now have a node too much in the list. In case the requested file was not found,
286 // we use this node to store the name of it, otherwise we free it.
287 if (currentNode == NULL)
288 {
289 StringCbPrintfExW(conductor->FileName, MAX_PATH, NULL, NULL, 0, L"%ls", szFirstFile);
290 currentNode = conductor;
291 }
292 else
293 {
294 conductor = conductor->Prev;
295 free(conductor->Next);
296 }
297
298 // link the last node with the first one to make the list circular
299 conductor->Next = root;
300 root->Prev = conductor;
301 conductor = currentNode;
302
303 free(codecInfo);
304
305 return conductor;
306 }
307
308 static VOID
309 pFreeFileList(SHIMGVW_FILENODE *root)
310 {
311 SHIMGVW_FILENODE *conductor;
312
313 root->Prev->Next = NULL;
314 root->Prev = NULL;
315
316 while (root)
317 {
318 conductor = root;
319 root = conductor->Next;
320 free(conductor);
321 }
322 }
323
324 static VOID
325 ImageView_UpdateWindow(HWND hwnd)
326 {
327 InvalidateRect(hwnd, NULL, FALSE);
328 UpdateWindow(hwnd);
329 }
330
331 static VOID
332 ImageView_DrawImage(HWND hwnd)
333 {
334 GpGraphics *graphics;
335 UINT uImgWidth, uImgHeight;
336 UINT height = 0, width = 0, x = 0, y = 0;
337 PAINTSTRUCT ps;
338 RECT rect;
339 HDC hdc;
340
341 hdc = BeginPaint(hwnd, &ps);
342 if (!hdc)
343 {
344 DPRINT1("BeginPaint() failed\n");
345 return;
346 }
347
348 GdipCreateFromHDC(hdc, &graphics);
349 if (!graphics)
350 {
351 DPRINT1("GdipCreateFromHDC() failed\n");
352 return;
353 }
354
355 GdipGetImageWidth(image, &uImgWidth);
356 GdipGetImageHeight(image, &uImgHeight);
357
358 if (GetClientRect(hwnd, &rect))
359 {
360 FillRect(hdc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
361
362 if ((rect.right >= uImgWidth)&&(rect.bottom >= uImgHeight))
363 {
364 width = uImgWidth;
365 height = uImgHeight;
366 }
367 else
368 {
369 height = uImgHeight * (UINT)rect.right / uImgWidth;
370 if (height <= rect.bottom)
371 {
372 width = rect.right;
373 }
374 else
375 {
376 width = uImgWidth * (UINT)rect.bottom / uImgHeight;
377 height = rect.bottom;
378 }
379 }
380
381 y = (rect.bottom / 2) - (height / 2);
382 x = (rect.right / 2) - (width / 2);
383
384 DPRINT("x = %d\ny = %d\nWidth = %d\nHeight = %d\n\nrect.right = %d\nrect.bottom = %d\n\nuImgWidth = %d\nuImgHeight = %d\n", x, y, width, height, rect.right, rect.bottom, uImgWidth, uImgHeight);
385 Rectangle(hdc, x - 1, y - 1, x + width + 1, y + height + 1);
386 GdipDrawImageRect(graphics, image, x, y, width, height);
387 }
388 GdipDeleteGraphics(graphics);
389 EndPaint(hwnd, &ps);
390 }
391
392 static BOOL
393 ImageView_LoadSettings()
394 {
395 HKEY hKey;
396 DWORD dwSize;
397
398 if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\ReactOS\\shimgvw"), 0, KEY_READ, &hKey) == ERROR_SUCCESS)
399 {
400 dwSize = sizeof(SHIMGVW_SETTINGS);
401 if (RegQueryValueEx(hKey, _T("Settings"), NULL, NULL, (LPBYTE)&shiSettings, &dwSize) == ERROR_SUCCESS)
402 {
403 RegCloseKey(hKey);
404 return TRUE;
405 }
406
407 RegCloseKey(hKey);
408 }
409
410 return FALSE;
411 }
412
413 static VOID
414 ImageView_SaveSettings(HWND hwnd)
415 {
416 WINDOWPLACEMENT wp;
417 HKEY hKey;
418
419 ShowWindow(hwnd, SW_HIDE);
420 wp.length = sizeof(WINDOWPLACEMENT);
421 GetWindowPlacement(hwnd, &wp);
422
423 shiSettings.Left = wp.rcNormalPosition.left;
424 shiSettings.Top = wp.rcNormalPosition.top;
425 shiSettings.Right = wp.rcNormalPosition.right;
426 shiSettings.Bottom = wp.rcNormalPosition.bottom;
427 shiSettings.Maximized = (IsZoomed(hwnd) || (wp.flags & WPF_RESTORETOMAXIMIZED));
428
429 if (RegCreateKeyEx(HKEY_CURRENT_USER, _T("Software\\ReactOS\\shimgvw"), 0, NULL,
430 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
431 {
432 RegSetValueEx(hKey, _T("Settings"), 0, REG_BINARY, (LPBYTE)&shiSettings, sizeof(SHIMGVW_SETTINGS));
433 RegCloseKey(hKey);
434 }
435 }
436
437 static BOOL
438 ImageView_CreateToolBar(HWND hwnd)
439 {
440 INT numButtons = sizeof(Buttons) / sizeof(Buttons[0]);
441
442 hToolBar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
443 WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | CCS_BOTTOM | TBSTYLE_TOOLTIPS,
444 0, 0, 0, 0, hwnd,
445 0, hInstance, NULL);
446 if(hToolBar != NULL)
447 {
448 HIMAGELIST hImageList;
449
450 SendMessage(hToolBar, TB_SETEXTENDEDSTYLE,
451 0, TBSTYLE_EX_HIDECLIPPEDBUTTONS);
452
453 SendMessage(hToolBar, TB_BUTTONSTRUCTSIZE,
454 sizeof(Buttons[0]), 0);
455
456 hImageList = ImageList_Create(TB_IMAGE_WIDTH, TB_IMAGE_HEIGHT, ILC_MASK | ILC_COLOR24, 1, 1);
457
458 ImageList_AddMasked(hImageList, LoadImage(hInstance, MAKEINTRESOURCE(IDB_PREVICON), IMAGE_BITMAP,
459 TB_IMAGE_WIDTH, TB_IMAGE_HEIGHT, LR_DEFAULTCOLOR), RGB(255, 255, 255));
460
461 ImageList_AddMasked(hImageList, LoadImage(hInstance, MAKEINTRESOURCE(IDB_NEXTICON), IMAGE_BITMAP,
462 TB_IMAGE_WIDTH, TB_IMAGE_HEIGHT, LR_DEFAULTCOLOR), RGB(255, 255, 255));
463
464 ImageList_AddMasked(hImageList, LoadImage(hInstance, MAKEINTRESOURCE(IDB_ZOOMPICON), IMAGE_BITMAP,
465 TB_IMAGE_WIDTH, TB_IMAGE_HEIGHT, LR_DEFAULTCOLOR), RGB(255, 255, 255));
466
467 ImageList_AddMasked(hImageList, LoadImage(hInstance, MAKEINTRESOURCE(IDB_ZOOMMICON), IMAGE_BITMAP,
468 TB_IMAGE_WIDTH, TB_IMAGE_HEIGHT, LR_DEFAULTCOLOR), RGB(255, 255, 255));
469
470 ImageList_AddMasked(hImageList, LoadImage(hInstance, MAKEINTRESOURCE(IDB_SAVEICON), IMAGE_BITMAP,
471 TB_IMAGE_WIDTH, TB_IMAGE_HEIGHT, LR_DEFAULTCOLOR), RGB(255, 255, 255));
472
473 ImageList_AddMasked(hImageList, LoadImage(hInstance, MAKEINTRESOURCE(IDB_PRINTICON), IMAGE_BITMAP,
474 TB_IMAGE_WIDTH, TB_IMAGE_HEIGHT, LR_DEFAULTCOLOR), RGB(255, 255, 255));
475
476 ImageList_AddMasked(hImageList, LoadImage(hInstance, MAKEINTRESOURCE(IDB_ROT1ICON), IMAGE_BITMAP,
477 TB_IMAGE_WIDTH, TB_IMAGE_HEIGHT, LR_DEFAULTCOLOR), RGB(255, 255, 255));
478
479 ImageList_AddMasked(hImageList, LoadImage(hInstance, MAKEINTRESOURCE(IDB_ROT2ICON), IMAGE_BITMAP,
480 TB_IMAGE_WIDTH, TB_IMAGE_HEIGHT, LR_DEFAULTCOLOR), RGB(255, 255, 255));
481
482 if (hImageList == NULL) return FALSE;
483
484 ImageList_Destroy((HIMAGELIST)SendMessage(hToolBar, TB_SETIMAGELIST,
485 0, (LPARAM)hImageList));
486
487 SendMessage(hToolBar, TB_ADDBUTTONS,
488 numButtons, (LPARAM)Buttons);
489
490 return TRUE;
491 }
492
493 return FALSE;
494 }
495
496 LRESULT CALLBACK
497 ImageView_DispWndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
498 {
499 switch (Message)
500 {
501 case WM_PAINT:
502 {
503 ImageView_DrawImage(hwnd);
504 return 0L;
505 }
506 }
507 return CallWindowProc(PrevProc, hwnd, Message, wParam, lParam);
508 }
509
510 static VOID
511 ImageView_InitControls(HWND hwnd)
512 {
513 MoveWindow(hwnd, shiSettings.Left, shiSettings.Top,
514 shiSettings.Right - shiSettings.Left,
515 shiSettings.Bottom - shiSettings.Top, TRUE);
516
517 if (shiSettings.Maximized) ShowWindow(hwnd, SW_MAXIMIZE);
518
519 hDispWnd = CreateWindowEx(0, _T("STATIC"), _T(""),
520 WS_CHILD | WS_VISIBLE,
521 0, 0, 0, 0, hwnd, NULL, hInstance, NULL);
522
523 SetClassLongPtr(hDispWnd, GCL_STYLE, CS_HREDRAW | CS_VREDRAW);
524 PrevProc = (WNDPROC) SetWindowLongPtr(hDispWnd, GWL_WNDPROC, (LPARAM) ImageView_DispWndProc);
525
526 ImageView_CreateToolBar(hwnd);
527 }
528
529 LRESULT CALLBACK
530 ImageView_WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
531 {
532 switch (Message)
533 {
534 case WM_CREATE:
535 {
536 ImageView_InitControls(hwnd);
537 return 0L;
538 }
539 case WM_COMMAND:
540 {
541 switch (wParam)
542 {
543 case IDC_PREV:
544 {
545 currentFile = currentFile->Prev;
546 pLoadImageFromNode(currentFile, hwnd);
547 }
548
549 break;
550 case IDC_NEXT:
551 {
552 currentFile = currentFile->Next;
553 pLoadImageFromNode(currentFile, hwnd);
554 }
555
556 break;
557 case IDC_ZOOMP:
558
559 break;
560 case IDC_ZOOMM:
561
562 break;
563 case IDC_SAVE:
564 pSaveImageAs(hwnd);
565
566 break;
567 case IDC_PRINT:
568
569 break;
570 case IDC_ROT1:
571 {
572 GdipImageRotateFlip(image, Rotate270FlipNone);
573 ImageView_UpdateWindow(hwnd);
574 }
575
576 break;
577 case IDC_ROT2:
578 {
579 GdipImageRotateFlip(image, Rotate90FlipNone);
580 ImageView_UpdateWindow(hwnd);
581 }
582
583 break;
584 }
585 }
586 break;
587
588 case WM_NOTIFY:
589 {
590 LPNMHDR pnmhdr = (LPNMHDR)lParam;
591
592 switch (pnmhdr->code)
593 {
594 case TTN_GETDISPINFO:
595 {
596 LPTOOLTIPTEXT lpttt;
597 UINT idButton;
598
599 lpttt = (LPTOOLTIPTEXT)lParam;
600 idButton = (UINT)lpttt->hdr.idFrom;
601 lpttt->hinst = hInstance;
602
603 switch (idButton)
604 {
605 case IDC_PREV:
606 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_PREV_PIC);
607 break;
608 case IDC_NEXT:
609 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_NEXT_PIC);
610 break;
611 case IDC_ZOOMP:
612 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_ZOOM_IN);
613 break;
614 case IDC_ZOOMM:
615 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_ZOOM_OUT);
616 break;
617 case IDC_SAVE:
618 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_SAVEAS);
619 break;
620 case IDC_PRINT:
621 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_PRINT);
622 break;
623 case IDC_ROT1:
624 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_ROT_COUNCW);
625 break;
626 case IDC_ROT2:
627 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_ROT_CLOCKW);
628 break;
629 }
630 return TRUE;
631 }
632 }
633 break;
634 }
635 case WM_SIZING:
636 {
637 LPRECT pRect = (LPRECT)lParam;
638 if (pRect->right-pRect->left < 350)
639 pRect->right = pRect->left + 350;
640
641 if (pRect->bottom-pRect->top < 290)
642 pRect->bottom = pRect->top + 290;
643 return TRUE;
644 }
645 case WM_SIZE:
646 {
647 RECT rc;
648 SendMessage(hToolBar, TB_AUTOSIZE, 0, 0);
649 GetWindowRect(hToolBar, &rc);
650 MoveWindow(hDispWnd, 1, 1, LOWORD(lParam) - 1, HIWORD(lParam) - (rc.bottom - rc.top) - 1, TRUE);
651 return 0L;
652 }
653 case WM_DESTROY:
654 {
655 ImageView_SaveSettings(hwnd);
656 SetWindowLongPtr(hDispWnd, GWL_WNDPROC, (LPARAM) PrevProc);
657 PostQuitMessage(0);
658 break;
659 }
660 }
661
662 return DefWindowProc(hwnd, Message, wParam, lParam);
663 }
664
665 LONG WINAPI
666 ImageView_CreateWindow(HWND hwnd, LPWSTR szFileName)
667 {
668 struct GdiplusStartupInput gdiplusStartupInput;
669 ULONG_PTR gdiplusToken;
670 WNDCLASS WndClass = {0};
671 TCHAR szBuf[512];
672 WCHAR szInitialFile[MAX_PATH];
673 HWND hMainWnd;
674 MSG msg;
675
676 if (!ImageView_LoadSettings())
677 {
678 shiSettings.Maximized = FALSE;
679 shiSettings.Left = 0;
680 shiSettings.Top = 0;
681 shiSettings.Right = 520;
682 shiSettings.Bottom = 400;
683 }
684
685 // Initialize GDI+
686 gdiplusStartupInput.GdiplusVersion = 1;
687 gdiplusStartupInput.DebugEventCallback = NULL;
688 gdiplusStartupInput.SuppressBackgroundThread = FALSE;
689 gdiplusStartupInput.SuppressExternalCodecs = FALSE;
690
691 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
692 pLoadImage(szFileName);
693
694 // Create the window
695 WndClass.lpszClassName = _T("shimgvw_window");
696 WndClass.lpfnWndProc = ImageView_WndProc;
697 WndClass.hInstance = hInstance;
698 WndClass.style = CS_HREDRAW | CS_VREDRAW;
699 WndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPICON));
700 WndClass.hCursor = LoadCursor(hInstance, IDC_ARROW);
701 WndClass.hbrBackground = (HBRUSH)COLOR_WINDOW;
702
703 if (!RegisterClass(&WndClass)) return -1;
704
705 LoadString(hInstance, IDS_APPTITLE, szBuf, sizeof(szBuf) / sizeof(TCHAR));
706 hMainWnd = CreateWindow(_T("shimgvw_window"), szBuf,
707 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CAPTION,
708 CW_USEDEFAULT, CW_USEDEFAULT,
709 0, 0, NULL, NULL, hInstance, NULL);
710
711 // make sure the path has no quotes on it
712 wcscpy(szInitialFile, szFileName);
713 PathUnquoteSpacesW(szInitialFile);
714
715 currentFile = pBuildFileList(szInitialFile);
716 if (currentFile)
717 {
718 pLoadImageFromNode(currentFile, hMainWnd);
719 }
720
721 // Show it
722 ShowWindow(hMainWnd, SW_SHOW);
723 UpdateWindow(hMainWnd);
724
725 // Message Loop
726 while(GetMessage(&msg,NULL,0,0))
727 {
728 TranslateMessage(&msg);
729 DispatchMessageW(&msg);
730 }
731
732 pFreeFileList(currentFile);
733
734 if (image)
735 GdipDisposeImage(image);
736 GdiplusShutdown(gdiplusToken);
737 return -1;
738 }
739
740 VOID WINAPI
741 ImageView_FullscreenW(HWND hwnd, HINSTANCE hInst, LPCWSTR path, int nShow)
742 {
743 ImageView_CreateWindow(hwnd, (LPWSTR)path);
744 }
745
746 VOID WINAPI
747 ImageView_Fullscreen(HWND hwnd, HINSTANCE hInst, LPCWSTR path, int nShow)
748 {
749 ImageView_CreateWindow(hwnd, (LPWSTR)path);
750 }
751
752 VOID WINAPI
753 ImageView_FullscreenA(HWND hwnd, HINSTANCE hInst, LPCSTR path, int nShow)
754 {
755 WCHAR szFile[MAX_PATH];
756
757 if (MultiByteToWideChar(CP_ACP, 0, (char*)path, strlen((char*)path)+1, szFile, MAX_PATH))
758 {
759 ImageView_CreateWindow(hwnd, (LPWSTR)szFile);
760 }
761 }
762
763 VOID WINAPI
764 ImageView_PrintTo(HWND hwnd, HINSTANCE hInst, LPCWSTR path, int nShow)
765 {
766 DPRINT("ImageView_PrintTo() not implemented\n");
767 }
768
769 VOID WINAPI
770 ImageView_PrintToA(HWND hwnd, HINSTANCE hInst, LPCSTR path, int nShow)
771 {
772 DPRINT("ImageView_PrintToA() not implemented\n");
773 }
774
775 VOID WINAPI
776 ImageView_PrintToW(HWND hwnd, HINSTANCE hInst, LPCWSTR path, int nShow)
777 {
778 DPRINT("ImageView_PrintToW() not implemented\n");
779 }
780
781 BOOL WINAPI
782 DllMain(IN HINSTANCE hinstDLL,
783 IN DWORD dwReason,
784 IN LPVOID lpvReserved)
785 {
786 switch (dwReason)
787 {
788 case DLL_PROCESS_ATTACH:
789 case DLL_THREAD_ATTACH:
790 hInstance = hinstDLL;
791 break;
792 }
793
794 return TRUE;
795 }
796