3 * PROJECT: ReactOS Picture and Fax Viewer
4 * FILE: dll/win32/shimgvw/shimgvw.c
6 * PROGRAMMER: Dmitry Chapyshev (dmitry@reactos.org)
12 #define WIN32_NO_STATUS
14 #define COM_NO_WINDOWS_H
37 SHIMGVW_SETTINGS shiSettings
;
39 WNDPROC PrevProc
= NULL
;
41 HWND hDispWnd
, hToolBar
;
44 static const TBBUTTON Buttons
[] =
45 { /* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */
46 {TBICON_PREV
, IDC_PREV
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
47 {TBICON_NEXT
, IDC_NEXT
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
48 {15, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0}, 0, 0},
49 {TBICON_ZOOMP
, IDC_ZOOMP
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
50 {TBICON_ZOOMM
, IDC_ZOOMM
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
51 {15, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0}, 0, 0},
52 {TBICON_ROT1
, IDC_ROT1
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
53 {TBICON_ROT2
, IDC_ROT2
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
54 {15, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0}, 0, 0},
55 {TBICON_SAVE
, IDC_SAVE
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
56 {TBICON_PRINT
, IDC_PRINT
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
59 static void pLoadImage(LPWSTR szOpenFileName
)
61 if (GetFileAttributesW(szOpenFileName
) == 0xFFFFFFFF)
63 DPRINT1("File %s not found!\n", szOpenFileName
);
67 GdipLoadImageFromFile(szOpenFileName
, &image
);
70 DPRINT1("GdipLoadImageFromFile() failed\n");
74 static void pSaveImageAs(HWND hwnd
)
77 ImageCodecInfo
*codecInfo
;
78 WCHAR szSaveFileName
[MAX_PATH
];
79 WCHAR szFilterMask
[2048];
87 ZeroMemory(szSaveFileName
, sizeof(szSaveFileName
));
88 ZeroMemory(szFilterMask
, sizeof(szFilterMask
));
89 ZeroMemory(&sfn
, sizeof(sfn
));
90 sfn
.lStructSize
= sizeof(sfn
);
92 sfn
.hInstance
= hInstance
;
93 sfn
.lpstrFile
= szSaveFileName
;
94 sfn
.lpstrFilter
= szFilterMask
;
95 sfn
.nMaxFile
= MAX_PATH
;
96 sfn
.Flags
= OFN_OVERWRITEPROMPT
| OFN_HIDEREADONLY
;
98 GdipGetImageEncodersSize(&num
, &size
);
99 codecInfo
= malloc(size
);
102 DPRINT1("malloc() failed in pSaveImageAs()\n");
106 GdipGetImageEncoders(num
, size
, codecInfo
);
107 GdipGetImageRawFormat(image
, &rawFormat
);
109 sizeRemain
= sizeof(szFilterMask
);
112 for (j
= 0; j
< num
; ++j
)
114 StringCbPrintfExW(c
, sizeRemain
, &c
, &sizeRemain
, 0, L
"%ls (%ls)", codecInfo
[j
].FormatDescription
, codecInfo
[j
].FilenameExtension
);
116 /* Skip the NULL character */
118 sizeRemain
-= sizeof(*c
);
120 StringCbPrintfExW(c
, sizeRemain
, &c
, &sizeRemain
, 0, L
"%ls", codecInfo
[j
].FilenameExtension
);
122 /* Skip the NULL character */
124 sizeRemain
-= sizeof(*c
);
126 if (IsEqualGUID(&rawFormat
, &codecInfo
[j
].FormatID
) == TRUE
)
128 sfn
.nFilterIndex
= j
+ 1;
132 if (GetSaveFileNameW(&sfn
))
134 if (GdipSaveImageToFile(image
, szSaveFileName
, &codecInfo
[sfn
.nFilterIndex
- 1].Clsid
, NULL
) != Ok
)
136 DPRINT1("GdipSaveImageToFile() failed\n");
144 ImageView_DrawImage(HWND hwnd
)
146 GpGraphics
*graphics
;
147 UINT uImgWidth
, uImgHeight
;
148 UINT height
= 0, width
= 0, x
= 0, y
= 0;
153 hdc
= BeginPaint(hwnd
, &ps
);
156 DPRINT1("BeginPaint() failed\n");
160 GdipCreateFromHDC(hdc
, &graphics
);
163 DPRINT1("GdipCreateFromHDC() failed\n");
167 GdipGetImageWidth(image
, &uImgWidth
);
168 GdipGetImageHeight(image
, &uImgHeight
);
170 if (GetClientRect(hwnd
, &rect
))
172 FillRect(hdc
, &rect
, (HBRUSH
)GetStockObject(WHITE_BRUSH
));
174 if ((rect
.right
== uImgWidth
)&&(rect
.bottom
== uImgHeight
))
176 x
= 0, y
= 0, width
= rect
.right
, height
= rect
.bottom
;
178 else if ((rect
.right
>= uImgWidth
)&&(rect
.bottom
>= uImgHeight
))
180 x
= (rect
.right
/2)-(uImgWidth
/2);
181 y
= (rect
.bottom
/2)-(uImgHeight
/2);
185 else if ((rect
.right
< uImgWidth
)||(rect
.bottom
< uImgHeight
))
187 if (rect
.bottom
< uImgHeight
)
189 height
= rect
.bottom
;
190 width
= uImgWidth
*(UINT
)rect
.bottom
/uImgHeight
;
191 x
= (rect
.right
/2)-(width
/2);
192 y
= (rect
.bottom
/2)-(height
/2);
194 if (rect
.right
< uImgWidth
)
197 height
= uImgHeight
*(UINT
)rect
.right
/uImgWidth
;
198 x
= (rect
.right
/2)-(width
/2);
199 y
= (rect
.bottom
/2)-(height
/2);
201 if ((height
> rect
.bottom
)||(width
> rect
.right
))
205 if (((int)width
- 1 < 0)||((int)height
- 1 < 0)) break;
208 y
= (rect
.bottom
/2)-(height
/2);
209 x
= (rect
.right
/2)-(width
/2);
210 if ((height
< rect
.bottom
)&&(width
< rect
.right
)) break;
214 else if ((rect
.right
<= uImgWidth
)&&(rect
.bottom
<= uImgHeight
))
216 height
= uImgHeight
*(UINT
)rect
.right
/uImgWidth
;
217 y
= (rect
.bottom
/2)-(height
/2);
220 if ((height
> rect
.bottom
)||(width
> rect
.right
))
224 if (((int)width
- 1 < 0)||((int)height
- 1 < 0)) break;
227 y
= (rect
.bottom
/2)-(height
/2);
228 x
= (rect
.right
/2)-(width
/2);
229 if ((height
< rect
.bottom
)&&(width
< rect
.right
)) break;
234 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
);
235 Rectangle(hdc
, x
- 1, y
- 1, x
+ width
+ 1, y
+ height
+ 1);
236 GdipDrawImageRect(graphics
, image
, x
, y
, width
, height
);
238 GdipDeleteGraphics(graphics
);
243 ImageView_LoadSettings()
248 if (RegOpenKeyEx(HKEY_CURRENT_USER
, _T("Software\\ReactOS\\shimgvw"), 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
250 dwSize
= sizeof(SHIMGVW_SETTINGS
);
251 if (RegQueryValueEx(hKey
, _T("Settings"), NULL
, NULL
, (LPBYTE
)&shiSettings
, &dwSize
) == ERROR_SUCCESS
)
264 ImageView_SaveSettings(HWND hwnd
)
269 ShowWindow(hwnd
, SW_HIDE
);
270 wp
.length
= sizeof(WINDOWPLACEMENT
);
271 GetWindowPlacement(hwnd
, &wp
);
273 shiSettings
.Left
= wp
.rcNormalPosition
.left
;
274 shiSettings
.Top
= wp
.rcNormalPosition
.top
;
275 shiSettings
.Right
= wp
.rcNormalPosition
.right
;
276 shiSettings
.Bottom
= wp
.rcNormalPosition
.bottom
;
277 shiSettings
.Maximized
= (IsZoomed(hwnd
) || (wp
.flags
& WPF_RESTORETOMAXIMIZED
));
279 if (RegCreateKeyEx(HKEY_CURRENT_USER
, _T("Software\\ReactOS\\shimgvw"), 0, NULL
,
280 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hKey
, NULL
) == ERROR_SUCCESS
)
282 RegSetValueEx(hKey
, _T("Settings"), 0, REG_BINARY
, (LPBYTE
)&shiSettings
, sizeof(SHIMGVW_SETTINGS
));
288 ImageView_CreateToolBar(HWND hwnd
)
290 INT numButtons
= sizeof(Buttons
) / sizeof(Buttons
[0]);
292 hToolBar
= CreateWindowEx(0, TOOLBARCLASSNAME
, NULL
,
293 WS_CHILD
| WS_VISIBLE
| TBSTYLE_FLAT
| CCS_BOTTOM
| TBSTYLE_TOOLTIPS
,
298 HIMAGELIST hImageList
;
300 SendMessage(hToolBar
, TB_SETEXTENDEDSTYLE
,
301 0, TBSTYLE_EX_HIDECLIPPEDBUTTONS
);
303 SendMessage(hToolBar
, TB_BUTTONSTRUCTSIZE
,
304 sizeof(Buttons
[0]), 0);
306 hImageList
= ImageList_Create(TB_IMAGE_WIDTH
, TB_IMAGE_HEIGHT
, ILC_MASK
| ILC_COLOR24
, 1, 1);
308 ImageList_AddMasked(hImageList
, LoadImage(hInstance
, MAKEINTRESOURCE(IDB_PREVICON
), IMAGE_BITMAP
,
309 TB_IMAGE_WIDTH
, TB_IMAGE_HEIGHT
, LR_DEFAULTCOLOR
), RGB(255, 255, 255));
311 ImageList_AddMasked(hImageList
, LoadImage(hInstance
, MAKEINTRESOURCE(IDB_NEXTICON
), IMAGE_BITMAP
,
312 TB_IMAGE_WIDTH
, TB_IMAGE_HEIGHT
, LR_DEFAULTCOLOR
), RGB(255, 255, 255));
314 ImageList_AddMasked(hImageList
, LoadImage(hInstance
, MAKEINTRESOURCE(IDB_ZOOMPICON
), IMAGE_BITMAP
,
315 TB_IMAGE_WIDTH
, TB_IMAGE_HEIGHT
, LR_DEFAULTCOLOR
), RGB(255, 255, 255));
317 ImageList_AddMasked(hImageList
, LoadImage(hInstance
, MAKEINTRESOURCE(IDB_ZOOMMICON
), IMAGE_BITMAP
,
318 TB_IMAGE_WIDTH
, TB_IMAGE_HEIGHT
, LR_DEFAULTCOLOR
), RGB(255, 255, 255));
320 ImageList_AddMasked(hImageList
, LoadImage(hInstance
, MAKEINTRESOURCE(IDB_SAVEICON
), IMAGE_BITMAP
,
321 TB_IMAGE_WIDTH
, TB_IMAGE_HEIGHT
, LR_DEFAULTCOLOR
), RGB(255, 255, 255));
323 ImageList_AddMasked(hImageList
, LoadImage(hInstance
, MAKEINTRESOURCE(IDB_PRINTICON
), IMAGE_BITMAP
,
324 TB_IMAGE_WIDTH
, TB_IMAGE_HEIGHT
, LR_DEFAULTCOLOR
), RGB(255, 255, 255));
326 ImageList_AddMasked(hImageList
, LoadImage(hInstance
, MAKEINTRESOURCE(IDB_ROT1ICON
), IMAGE_BITMAP
,
327 TB_IMAGE_WIDTH
, TB_IMAGE_HEIGHT
, LR_DEFAULTCOLOR
), RGB(255, 255, 255));
329 ImageList_AddMasked(hImageList
, LoadImage(hInstance
, MAKEINTRESOURCE(IDB_ROT2ICON
), IMAGE_BITMAP
,
330 TB_IMAGE_WIDTH
, TB_IMAGE_HEIGHT
, LR_DEFAULTCOLOR
), RGB(255, 255, 255));
332 if (hImageList
== NULL
) return FALSE
;
334 ImageList_Destroy((HIMAGELIST
)SendMessage(hToolBar
, TB_SETIMAGELIST
,
335 0, (LPARAM
)hImageList
));
337 SendMessage(hToolBar
, TB_ADDBUTTONS
,
338 numButtons
, (LPARAM
)Buttons
);
347 ImageView_DispWndProc(HWND hwnd
, UINT Message
, WPARAM wParam
, LPARAM lParam
)
353 ImageView_DrawImage(hwnd
);
357 return CallWindowProc(PrevProc
, hwnd
, Message
, wParam
, lParam
);
361 ImageView_InitControls(HWND hwnd
)
363 MoveWindow(hwnd
, shiSettings
.Left
, shiSettings
.Top
,
364 shiSettings
.Right
- shiSettings
.Left
,
365 shiSettings
.Bottom
- shiSettings
.Top
, TRUE
);
367 if (shiSettings
.Maximized
) ShowWindow(hwnd
, SW_MAXIMIZE
);
369 hDispWnd
= CreateWindowEx(0, _T("STATIC"), _T(""),
370 WS_CHILD
| WS_VISIBLE
,
371 0, 0, 0, 0, hwnd
, NULL
, hInstance
, NULL
);
373 SetClassLongPtr(hDispWnd
, GCL_STYLE
, CS_HREDRAW
| CS_VREDRAW
);
374 PrevProc
= (WNDPROC
) SetWindowLongPtr(hDispWnd
, GWL_WNDPROC
, (LPARAM
) ImageView_DispWndProc
);
376 ImageView_CreateToolBar(hwnd
);
380 ImageView_WndProc(HWND hwnd
, UINT Message
, WPARAM wParam
, LPARAM lParam
)
386 ImageView_InitControls(hwnd
);
424 LPNMHDR pnmhdr
= (LPNMHDR
)lParam
;
426 switch (pnmhdr
->code
)
428 case TTN_GETDISPINFO
:
433 lpttt
= (LPTOOLTIPTEXT
)lParam
;
434 idButton
= (UINT
)lpttt
->hdr
.idFrom
;
439 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_PREV_PIC
);
442 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_NEXT_PIC
);
445 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_ZOOM_IN
);
448 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_ZOOM_OUT
);
451 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_SAVEAS
);
454 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_PRINT
);
457 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_ROT_COUNCW
);
460 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_ROT_CLOCKW
);
470 LPRECT pRect
= (LPRECT
)lParam
;
471 if (pRect
->right
-pRect
->left
< 350)
472 pRect
->right
= pRect
->left
+ 350;
474 if (pRect
->bottom
-pRect
->top
< 290)
475 pRect
->bottom
= pRect
->top
+ 290;
481 SendMessage(hToolBar
, TB_AUTOSIZE
, 0, 0);
482 SendMessage(hToolBar
, TB_GETITEMRECT
, 1, (LPARAM
)&rc
);
483 MoveWindow(hDispWnd
, 1, 1, LOWORD(lParam
)-1, HIWORD(lParam
)-rc
.bottom
, TRUE
);
488 ImageView_SaveSettings(hwnd
);
489 SetWindowLongPtr(hDispWnd
, GWL_WNDPROC
, (LPARAM
) PrevProc
);
495 return DefWindowProc(hwnd
, Message
, wParam
, lParam
);
499 ImageView_CreateWindow(HWND hwnd
, LPWSTR szFileName
)
501 struct GdiplusStartupInput gdiplusStartupInput
;
502 ULONG_PTR gdiplusToken
;
503 WNDCLASS WndClass
= {0};
508 if (!ImageView_LoadSettings())
510 shiSettings
.Maximized
= FALSE
;
511 shiSettings
.Left
= 0;
513 shiSettings
.Right
= 520;
514 shiSettings
.Bottom
= 400;
518 gdiplusStartupInput
.GdiplusVersion
= 1;
519 gdiplusStartupInput
.DebugEventCallback
= NULL
;
520 gdiplusStartupInput
.SuppressBackgroundThread
= FALSE
;
521 gdiplusStartupInput
.SuppressExternalCodecs
= FALSE
;
523 GdiplusStartup(&gdiplusToken
, &gdiplusStartupInput
, NULL
);
524 pLoadImage(szFileName
);
527 WndClass
.lpszClassName
= _T("shimgvw_window");
528 WndClass
.lpfnWndProc
= ImageView_WndProc
;
529 WndClass
.hInstance
= hInstance
;
530 WndClass
.style
= CS_HREDRAW
| CS_VREDRAW
;
531 WndClass
.hIcon
= LoadIcon(hInstance
, MAKEINTRESOURCE(IDI_APPICON
));
532 WndClass
.hCursor
= LoadCursor(hInstance
, IDC_ARROW
);
533 WndClass
.hbrBackground
= (HBRUSH
)COLOR_WINDOW
;
535 if (!RegisterClass(&WndClass
)) return -1;
537 LoadString(hInstance
, IDS_APPTITLE
, szBuf
, sizeof(szBuf
) / sizeof(TCHAR
));
538 hMainWnd
= CreateWindow(_T("shimgvw_window"), szBuf
,
539 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
| WS_CAPTION
,
540 CW_USEDEFAULT
, CW_USEDEFAULT
,
541 0, 0, NULL
, NULL
, hInstance
, NULL
);
544 ShowWindow(hMainWnd
, SW_SHOW
);
545 UpdateWindow(hMainWnd
);
548 while(GetMessage(&msg
,NULL
,0,0))
550 TranslateMessage(&msg
);
551 DispatchMessageW(&msg
);
555 GdipDisposeImage(image
);
556 GdiplusShutdown(gdiplusToken
);
561 ImageView_FullscreenW(HWND hwnd
, HINSTANCE hInst
, LPCWSTR path
, int nShow
)
563 ImageView_CreateWindow(hwnd
, (LPWSTR
)path
);
567 ImageView_Fullscreen(HWND hwnd
, HINSTANCE hInst
, LPCWSTR path
, int nShow
)
569 ImageView_CreateWindow(hwnd
, (LPWSTR
)path
);
573 ImageView_FullscreenA(HWND hwnd
, HINSTANCE hInst
, LPCSTR path
, int nShow
)
575 WCHAR szFile
[MAX_PATH
];
577 if (MultiByteToWideChar(CP_ACP
, 0, (char*)path
, strlen((char*)path
)+1, szFile
, MAX_PATH
))
579 ImageView_CreateWindow(hwnd
, (LPWSTR
)szFile
);
584 ImageView_PrintTo(HWND hwnd
, HINSTANCE hInst
, LPCWSTR path
, int nShow
)
586 DPRINT("ImageView_PrintTo() not implemented\n");
590 ImageView_PrintToA(HWND hwnd
, HINSTANCE hInst
, LPCSTR path
, int nShow
)
592 DPRINT("ImageView_PrintToA() not implemented\n");
596 ImageView_PrintToW(HWND hwnd
, HINSTANCE hInst
, LPCWSTR path
, int nShow
)
598 DPRINT("ImageView_PrintToW() not implemented\n");
602 DllMain(IN HINSTANCE hinstDLL
,
604 IN LPVOID lpvReserved
)
608 case DLL_PROCESS_ATTACH
:
609 case DLL_THREAD_ATTACH
:
610 hInstance
= hinstDLL
;