1 // TortoiseIDiff - an image diff viewer in TortoiseSVN
3 // Copyright (C) 2006 - 2009 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "TortoiseIDiff.h"
23 #include "MainWindow.h"
26 #pragma comment(lib, "comctl32.lib")
28 tstring
CMainWindow::leftpicpath
;
29 tstring
CMainWindow::leftpictitle
;
31 tstring
CMainWindow::rightpicpath
;
32 tstring
CMainWindow::rightpictitle
;
34 bool CMainWindow::RegisterAndCreateWindow()
38 // Fill in the window class structure with default parameters
39 wcx
.cbSize
= sizeof(WNDCLASSEX
);
40 wcx
.style
= CS_HREDRAW
| CS_VREDRAW
;
41 wcx
.lpfnWndProc
= CWindow::stWinMsgHandler
;
44 wcx
.hInstance
= hResource
;
45 wcx
.hCursor
= LoadCursor(NULL
, IDC_SIZEWE
);
46 wcx
.lpszClassName
= ResString(hResource
, IDS_APP_TITLE
);
47 wcx
.hIcon
= LoadIcon(hResource
, MAKEINTRESOURCE(IDI_TORTOISEIDIFF
));
48 wcx
.hbrBackground
= (HBRUSH
)(COLOR_3DFACE
+1);
49 wcx
.lpszMenuName
= MAKEINTRESOURCE(IDC_TORTOISEIDIFF
);
50 wcx
.hIconSm
= LoadIcon(wcx
.hInstance
, MAKEINTRESOURCE(IDI_TORTOISEIDIFF
));
51 if (RegisterWindow(&wcx
))
53 if (Create(WS_OVERLAPPEDWINDOW
| WS_CLIPCHILDREN
| WS_VISIBLE
, NULL
))
55 ShowWindow(m_hwnd
, SW_SHOW
);
63 void CMainWindow::PositionChildren(RECT
* clientrect
/* = NULL */)
66 if (clientrect
== NULL
)
68 SendMessage(hwndTB
, TB_AUTOSIZE
, 0, 0);
69 GetWindowRect(hwndTB
, &tbRect
);
70 LONG tbHeight
= tbRect
.bottom
-tbRect
.top
-1;
71 HDWP hdwp
= BeginDeferWindowPos(2);
74 SetWindowPos(picWindow1
, NULL
, clientrect
->left
, clientrect
->top
+tbHeight
, clientrect
->right
-clientrect
->left
, clientrect
->bottom
-clientrect
->top
-tbHeight
, SWP_SHOWWINDOW
);
81 child
.left
= clientrect
->left
;
82 child
.top
= clientrect
->top
+tbHeight
;
83 child
.right
= clientrect
->right
;
84 child
.bottom
= nSplitterPos
-(SPLITTER_BORDER
/2);
85 if (hdwp
) hdwp
= DeferWindowPos(hdwp
, picWindow1
, NULL
, child
.left
, child
.top
, child
.right
-child
.left
, child
.bottom
-child
.top
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
);
86 child
.top
= nSplitterPos
+(SPLITTER_BORDER
/2);
87 child
.bottom
= clientrect
->bottom
;
88 if (hdwp
) hdwp
= DeferWindowPos(hdwp
, picWindow2
, NULL
, child
.left
, child
.top
, child
.right
-child
.left
, child
.bottom
-child
.top
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
);
93 child
.left
= clientrect
->left
;
94 child
.top
= clientrect
->top
+tbHeight
;
95 child
.right
= nSplitterPos
-(SPLITTER_BORDER
/2);
96 child
.bottom
= clientrect
->bottom
;
97 if (hdwp
) hdwp
= DeferWindowPos(hdwp
, picWindow1
, NULL
, child
.left
, child
.top
, child
.right
-child
.left
, child
.bottom
-child
.top
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
);
98 child
.left
= nSplitterPos
+(SPLITTER_BORDER
/2);
99 child
.right
= clientrect
->right
;
100 if (hdwp
) hdwp
= DeferWindowPos(hdwp
, picWindow2
, NULL
, child
.left
, child
.top
, child
.right
-child
.left
, child
.bottom
-child
.top
, SWP_FRAMECHANGED
|SWP_SHOWWINDOW
);
103 if (hdwp
) EndDeferWindowPos(hdwp
);
104 picWindow1
.SetTransparentColor(transparentColor
);
105 picWindow2
.SetTransparentColor(transparentColor
);
106 InvalidateRect(*this, NULL
, FALSE
);
109 LRESULT CALLBACK
CMainWindow::WinMsgHandler(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
116 picWindow1
.RegisterAndCreateWindow(hwnd
);
117 picWindow1
.SetPic(leftpicpath
, leftpictitle
, true);
118 picWindow2
.RegisterAndCreateWindow(hwnd
);
119 picWindow2
.SetPic(rightpicpath
, rightpictitle
, false);
121 picWindow1
.SetOtherPicWindow(&picWindow2
);
122 picWindow2
.SetOtherPicWindow(&picWindow1
);
123 // center the splitter
125 GetClientRect(hwnd
, &rect
);
126 nSplitterPos
= (rect
.right
-rect
.left
-SPLITTER_BORDER
)/2;
128 PositionChildren(&rect
);
129 picWindow1
.FitImageInWindow();
130 picWindow2
.FitImageInWindow();
135 return DoCommand(LOWORD(wParam
));
144 ::GetClientRect(*this, &rect
);
145 hdc
= BeginPaint(hwnd
, &ps
);
146 SetBkColor(hdc
, GetSysColor(COLOR_3DFACE
));
147 ::ExtTextOut(hdc
, 0, 0, ETO_OPAQUE
, &rect
, NULL
, 0, NULL
);
151 case WM_GETMINMAXINFO
:
153 MINMAXINFO
* mmi
= (MINMAXINFO
*)lParam
;
154 mmi
->ptMinTrackSize
.x
= WINDOW_MINWIDTH
;
155 mmi
->ptMinTrackSize
.y
= WINDOW_MINHEIGHT
;
162 GetClientRect(hwnd
, &rect
);
166 GetWindowRect(hwndTB
, &tbRect
);
167 LONG tbHeight
= tbRect
.bottom
-tbRect
.top
-1;
168 nSplitterPos
= (rect
.bottom
-rect
.top
-SPLITTER_BORDER
+tbHeight
)/2;
171 nSplitterPos
= (rect
.right
-rect
.left
-SPLITTER_BORDER
)/2;
172 PositionChildren(&rect
);
177 if ((HWND
)wParam
== *this)
181 GetClientRect(*this, &rect
);
183 ScreenToClient(*this, &pt
);
184 if (PtInRect(&rect
, pt
))
188 HCURSOR hCur
= LoadCursor(NULL
, MAKEINTRESOURCE(IDC_SIZENS
));
193 HCURSOR hCur
= LoadCursor(NULL
, MAKEINTRESOURCE(IDC_SIZEWE
));
199 return DefWindowProc(hwnd
, uMsg
, wParam
, lParam
);
203 Splitter_OnLButtonDown(hwnd
, uMsg
, wParam
, lParam
);
206 Splitter_OnLButtonUp(hwnd
, uMsg
, wParam
, lParam
);
209 Splitter_OnMouseMove(hwnd
, uMsg
, wParam
, lParam
);
213 // find out if the mouse cursor is over one of the views, and if
214 // it is, pass the mouse wheel message to that view
216 DWORD ptW
= GetMessagePos();
217 pt
.x
= GET_X_LPARAM(ptW
);
218 pt
.y
= GET_Y_LPARAM(ptW
);
220 GetWindowRect(picWindow1
, &rect
);
221 if (PtInRect(&rect
, pt
))
223 picWindow1
.OnMouseWheel(GET_KEYSTATE_WPARAM(wParam
), GET_WHEEL_DELTA_WPARAM(wParam
));
227 GetWindowRect(picWindow2
, &rect
);
228 if (PtInRect(&rect
, pt
))
230 picWindow2
.OnMouseWheel(GET_KEYSTATE_WPARAM(wParam
), GET_WHEEL_DELTA_WPARAM(wParam
));
237 // find out if the mouse cursor is over one of the views, and if
238 // it is, pass the mouse wheel message to that view
240 DWORD ptW
= GetMessagePos();
241 pt
.x
= GET_X_LPARAM(ptW
);
242 pt
.y
= GET_Y_LPARAM(ptW
);
244 GetWindowRect(picWindow1
, &rect
);
245 if (PtInRect(&rect
, pt
))
247 picWindow1
.OnMouseWheel(GET_KEYSTATE_WPARAM(wParam
)|MK_SHIFT
, GET_WHEEL_DELTA_WPARAM(wParam
));
251 GetWindowRect(picWindow2
, &rect
);
252 if (PtInRect(&rect
, pt
))
254 picWindow2
.OnMouseWheel(GET_KEYSTATE_WPARAM(wParam
)|MK_SHIFT
, GET_WHEEL_DELTA_WPARAM(wParam
));
261 LPNMHDR pNMHDR
= (LPNMHDR
)lParam
;
262 if (pNMHDR
->code
== TTN_GETDISPINFO
)
266 lpttt
= (LPTOOLTIPTEXT
) lParam
;
267 lpttt
->hinst
= hResource
;
269 // Specify the resource identifier of the descriptive
270 // text for the given button.
271 TCHAR stringbuf
[MAX_PATH
] = {0};
273 mii
.cbSize
= sizeof(MENUITEMINFO
);
274 mii
.fMask
= MIIM_TYPE
;
275 mii
.dwTypeData
= stringbuf
;
276 mii
.cch
= sizeof(stringbuf
)/sizeof(TCHAR
);
277 GetMenuItemInfo(GetMenu(*this), (UINT
)lpttt
->hdr
.idFrom
, FALSE
, &mii
);
278 lpttt
->lpszText
= stringbuf
;
283 bWindowClosed
= TRUE
;
287 ImageList_Destroy(hToolbarImgList
);
288 ::DestroyWindow(m_hwnd
);
291 return DefWindowProc(hwnd
, uMsg
, wParam
, lParam
);
297 LRESULT
CMainWindow::DoCommand(int id
)
305 picWindow1
.SetPic(leftpicpath
, _T(""), true);
306 picWindow2
.SetPic(rightpicpath
, _T(""), false);
309 picWindow1
.SetSecondPic(picWindow2
.GetPic(), rightpictitle
, rightpicpath
);
313 picWindow1
.SetSecondPic();
316 GetClientRect(*this, &rect
);
317 PositionChildren(&rect
);
318 picWindow1
.FitImageInWindow();
319 picWindow2
.FitImageInWindow();
323 case ID_VIEW_IMAGEINFO
:
325 bShowInfo
= !bShowInfo
;
326 HMENU hMenu
= GetMenu(*this);
327 UINT uCheck
= MF_BYCOMMAND
;
328 uCheck
|= bShowInfo
? MF_CHECKED
: MF_UNCHECKED
;
329 CheckMenuItem(hMenu
, ID_VIEW_IMAGEINFO
, uCheck
);
331 picWindow1
.ShowInfo(bShowInfo
);
332 picWindow2
.ShowInfo(bShowInfo
);
334 // change the state of the toolbar button
336 tbi
.cbSize
= sizeof(TBBUTTONINFO
);
337 tbi
.dwMask
= TBIF_STATE
;
338 tbi
.fsState
= bShowInfo
? TBSTATE_CHECKED
| TBSTATE_ENABLED
: TBSTATE_ENABLED
;
339 SendMessage(hwndTB
, TB_SETBUTTONINFO
, ID_VIEW_IMAGEINFO
, (LPARAM
)&tbi
);
342 case ID_VIEW_OVERLAPIMAGES
:
344 bOverlap
= !bOverlap
;
345 HMENU hMenu
= GetMenu(*this);
346 UINT uCheck
= MF_BYCOMMAND
;
347 uCheck
|= bOverlap
? MF_CHECKED
: MF_UNCHECKED
;
348 CheckMenuItem(hMenu
, ID_VIEW_OVERLAPIMAGES
, uCheck
);
349 uCheck
|= (m_BlendType
== CPicWindow::BLEND_ALPHA
) ? MF_CHECKED
: MF_UNCHECKED
;
350 CheckMenuItem(hMenu
, ID_VIEW_BLENDALPHA
, uCheck
);
352 // change the state of the toolbar button
354 tbi
.cbSize
= sizeof(TBBUTTONINFO
);
355 tbi
.dwMask
= TBIF_STATE
;
356 tbi
.fsState
= bOverlap
? TBSTATE_CHECKED
| TBSTATE_ENABLED
: TBSTATE_ENABLED
;
357 SendMessage(hwndTB
, TB_SETBUTTONINFO
, ID_VIEW_OVERLAPIMAGES
, (LPARAM
)&tbi
);
359 tbi
.fsState
= (m_BlendType
== CPicWindow::BLEND_ALPHA
) ? TBSTATE_CHECKED
: 0;
361 tbi
.fsState
|= TBSTATE_ENABLED
;
364 SendMessage(hwndTB
, TB_SETBUTTONINFO
, ID_VIEW_BLENDALPHA
, (LPARAM
)&tbi
);
369 tbi
.fsState
= bVertical
? TBSTATE_ENABLED
| TBSTATE_CHECKED
: TBSTATE_ENABLED
;
370 SendMessage(hwndTB
, TB_SETBUTTONINFO
, ID_VIEW_ARRANGEVERTICAL
, (LPARAM
)&tbi
);
372 ShowWindow(picWindow2
, bOverlap
? SW_HIDE
: SW_SHOW
);
376 picWindow1
.StopTimer();
377 picWindow2
.StopTimer();
378 picWindow1
.SetSecondPic(picWindow2
.GetPic(), rightpictitle
, rightpicpath
,
379 picWindow2
.GetHPos(), picWindow2
.GetVPos());
380 picWindow1
.SetBlendAlpha(m_BlendType
, 0.5f
);
384 picWindow1
.SetSecondPic();
389 GetClientRect(*this, &rect
);
390 PositionChildren(&rect
);
392 if ((bFitSizes
)&&(bOverlap
))
394 picWindow1
.FitSizes(bFitSizes
);
399 case ID_VIEW_BLENDALPHA
:
401 if (m_BlendType
== CPicWindow::BLEND_ALPHA
)
402 m_BlendType
= CPicWindow::BLEND_XOR
;
404 m_BlendType
= CPicWindow::BLEND_ALPHA
;
406 HMENU hMenu
= GetMenu(*this);
407 UINT uCheck
= MF_BYCOMMAND
;
408 uCheck
|= (m_BlendType
== CPicWindow::BLEND_ALPHA
) ? MF_CHECKED
: MF_UNCHECKED
;
409 CheckMenuItem(hMenu
, ID_VIEW_BLENDALPHA
, uCheck
);
411 // change the state of the toolbar button
413 tbi
.cbSize
= sizeof(TBBUTTONINFO
);
414 tbi
.dwMask
= TBIF_STATE
;
415 tbi
.fsState
= (m_BlendType
== CPicWindow::BLEND_ALPHA
) ? TBSTATE_CHECKED
| TBSTATE_ENABLED
: TBSTATE_ENABLED
;
416 SendMessage(hwndTB
, TB_SETBUTTONINFO
, ID_VIEW_BLENDALPHA
, (LPARAM
)&tbi
);
417 picWindow1
.SetBlendAlpha(m_BlendType
, picWindow1
.GetBlendAlpha());
421 case ID_VIEW_TRANSPARENTCOLOR
:
423 static COLORREF customColors
[16] = {0};
425 memset(&ccDlg
, 0, sizeof(ccDlg
));
426 ccDlg
.lStructSize
= sizeof(ccDlg
);
427 ccDlg
.hwndOwner
= m_hwnd
;
428 ccDlg
.rgbResult
= transparentColor
;
429 ccDlg
.lpCustColors
= customColors
;
430 ccDlg
.Flags
= CC_RGBINIT
| CC_FULLOPEN
;
431 if(ChooseColor(&ccDlg
))
433 transparentColor
= ccDlg
.rgbResult
;
434 picWindow1
.SetTransparentColor(transparentColor
);
435 picWindow2
.SetTransparentColor(transparentColor
);
436 // The color picker takes the focus and we don't get it back.
437 ::SetFocus(picWindow1
);
441 case ID_VIEW_FITTOGETHER
:
443 bFitSizes
= !bFitSizes
;
444 picWindow1
.FitSizes(bFitSizes
);
445 picWindow2
.FitSizes(bFitSizes
);
447 HMENU hMenu
= GetMenu(*this);
448 UINT uCheck
= MF_BYCOMMAND
;
449 uCheck
|= bFitSizes
? MF_CHECKED
: MF_UNCHECKED
;
450 CheckMenuItem(hMenu
, ID_VIEW_FITTOGETHER
, uCheck
);
452 // change the state of the toolbar button
454 tbi
.cbSize
= sizeof(TBBUTTONINFO
);
455 tbi
.dwMask
= TBIF_STATE
;
456 tbi
.fsState
= bFitSizes
? TBSTATE_CHECKED
| TBSTATE_ENABLED
: TBSTATE_ENABLED
;
457 SendMessage(hwndTB
, TB_SETBUTTONINFO
, ID_VIEW_FITTOGETHER
, (LPARAM
)&tbi
);
460 case ID_VIEW_LINKIMAGESTOGETHER
:
462 bLinkedPositions
= !bLinkedPositions
;
463 picWindow1
.LinkPositions(bLinkedPositions
);
464 picWindow2
.LinkPositions(bLinkedPositions
);
466 HMENU hMenu
= GetMenu(*this);
467 UINT uCheck
= MF_BYCOMMAND
;
468 uCheck
|= bLinkedPositions
? MF_CHECKED
: MF_UNCHECKED
;
469 CheckMenuItem(hMenu
, ID_VIEW_LINKIMAGESTOGETHER
, uCheck
);
471 // change the state of the toolbar button
473 tbi
.cbSize
= sizeof(TBBUTTONINFO
);
474 tbi
.dwMask
= TBIF_STATE
;
475 tbi
.fsState
= bLinkedPositions
? TBSTATE_CHECKED
| TBSTATE_ENABLED
: TBSTATE_ENABLED
;
476 SendMessage(hwndTB
, TB_SETBUTTONINFO
, ID_VIEW_LINKIMAGESTOGETHER
, (LPARAM
)&tbi
);
480 picWindow1
.SetBlendAlpha(m_BlendType
, 0.0f
);
482 case ID_VIEW_ALPHA255
:
483 picWindow1
.SetBlendAlpha(m_BlendType
, 1.0f
);
485 case ID_VIEW_ALPHA127
:
486 picWindow1
.SetBlendAlpha(m_BlendType
, 0.5f
);
488 case ID_VIEW_ALPHATOGGLE
:
489 picWindow1
.ToggleAlpha();
491 case ID_VIEW_FITIMAGESINWINDOW
:
493 picWindow1
.FitImageInWindow();
494 picWindow2
.FitImageInWindow();
497 case ID_VIEW_ORININALSIZE
:
499 picWindow1
.SetZoom(1.0, false);
500 picWindow2
.SetZoom(1.0, false);
505 picWindow1
.Zoom(true, false);
507 picWindow2
.Zoom(true, false);
510 case ID_VIEW_ZOOMOUT
:
512 picWindow1
.Zoom(false, false);
514 picWindow2
.Zoom(false, false);
517 case ID_VIEW_ARRANGEVERTICAL
:
519 bVertical
= !bVertical
;
521 GetClientRect(*this, &rect
);
525 GetWindowRect(hwndTB
, &tbRect
);
526 LONG tbHeight
= tbRect
.bottom
-tbRect
.top
-1;
527 nSplitterPos
= (rect
.bottom
-rect
.top
-SPLITTER_BORDER
+tbHeight
)/2;
531 nSplitterPos
= (rect
.right
-rect
.left
-SPLITTER_BORDER
)/2;
533 HMENU hMenu
= GetMenu(*this);
534 UINT uCheck
= MF_BYCOMMAND
;
535 uCheck
|= bVertical
? MF_CHECKED
: MF_UNCHECKED
;
536 CheckMenuItem(hMenu
, ID_VIEW_ARRANGEVERTICAL
, uCheck
);
537 // change the state of the toolbar button
539 tbi
.cbSize
= sizeof(TBBUTTONINFO
);
540 tbi
.dwMask
= TBIF_STATE
;
541 tbi
.fsState
= bVertical
? TBSTATE_CHECKED
| TBSTATE_ENABLED
: TBSTATE_ENABLED
;
542 SendMessage(hwndTB
, TB_SETBUTTONINFO
, ID_VIEW_ARRANGEVERTICAL
, (LPARAM
)&tbi
);
544 PositionChildren(&rect
);
549 CAboutDlg
dlg(*this);
550 dlg
.DoModal(hInst
, IDD_ABOUT
, *this);
554 ::PostQuitMessage(0);
564 void CMainWindow::DrawXorBar(HDC hdc
, int x1
, int y1
, int width
, int height
)
566 static WORD _dotPatternBmp
[8] =
568 0x0055, 0x00aa, 0x0055, 0x00aa,
569 0x0055, 0x00aa, 0x0055, 0x00aa
573 HBRUSH hbr
, hbrushOld
;
575 hbm
= CreateBitmap(8, 8, 1, 1, _dotPatternBmp
);
576 hbr
= CreatePatternBrush(hbm
);
578 SetBrushOrgEx(hdc
, x1
, y1
, 0);
579 hbrushOld
= (HBRUSH
)SelectObject(hdc
, hbr
);
581 PatBlt(hdc
, x1
, y1
, width
, height
, PATINVERT
);
583 SelectObject(hdc
, hbrushOld
);
589 LRESULT
CMainWindow::Splitter_OnLButtonDown(HWND hwnd
, UINT iMsg
, WPARAM wParam
, LPARAM lParam
)
596 pt
.x
= (short)LOWORD(lParam
); // horizontal position of cursor
597 pt
.y
= (short)HIWORD(lParam
);
599 GetClientRect(hwnd
, &clientrect
);
600 GetWindowRect(hwnd
, &rect
);
602 ClientToScreen(hwnd
, &zero
);
603 OffsetRect(&clientrect
, zero
.x
-rect
.left
, zero
.y
-rect
.top
);
605 //convert the mouse coordinates relative to the top-left of
607 ClientToScreen(hwnd
, &pt
);
611 //same for the window coordinates - make them relative to 0,0
612 OffsetRect(&rect
, -rect
.left
, -rect
.top
);
616 if (pt
.x
> rect
.right
-4)
620 if (pt
.y
> rect
.bottom
-4)
621 pt
.y
= rect
.bottom
-4;
627 hdc
= GetWindowDC(hwnd
);
629 DrawXorBar(hdc
, clientrect
.left
, pt
.y
+2, clientrect
.right
-clientrect
.left
-2, 4);
631 DrawXorBar(hdc
, pt
.x
+2, clientrect
.top
, 4, clientrect
.bottom
-clientrect
.top
-2);
632 ReleaseDC(hwnd
, hdc
);
641 LRESULT
CMainWindow::Splitter_OnLButtonUp(HWND hwnd
, UINT iMsg
, WPARAM wParam
, LPARAM lParam
)
648 pt
.x
= (short)LOWORD(lParam
); // horizontal position of cursor
649 pt
.y
= (short)HIWORD(lParam
);
651 if (bDragMode
== FALSE
)
654 GetClientRect(hwnd
, &clientrect
);
655 GetWindowRect(hwnd
, &rect
);
657 ClientToScreen(hwnd
, &zero
);
658 OffsetRect(&clientrect
, zero
.x
-rect
.left
, zero
.y
-rect
.top
);
660 ClientToScreen(hwnd
, &pt
);
664 OffsetRect(&rect
, -rect
.left
, -rect
.top
);
668 if (pt
.x
> rect
.right
-4)
672 if (pt
.y
> rect
.bottom
-4)
673 pt
.y
= rect
.bottom
-4;
675 hdc
= GetWindowDC(hwnd
);
677 DrawXorBar(hdc
, clientrect
.left
, oldy
+2, clientrect
.right
-clientrect
.left
-2, 4);
679 DrawXorBar(hdc
, oldx
+2, clientrect
.top
, 4, clientrect
.bottom
-clientrect
.top
-2);
680 ReleaseDC(hwnd
, hdc
);
687 //convert the splitter position back to screen coords.
688 GetWindowRect(hwnd
, &rect
);
692 //now convert into CLIENT coordinates
693 ScreenToClient(hwnd
, &pt
);
694 GetClientRect(hwnd
, &rect
);
702 //position the child controls
703 PositionChildren(&rect
);
707 LRESULT
CMainWindow::Splitter_OnMouseMove(HWND hwnd
, UINT iMsg
, WPARAM wParam
, LPARAM lParam
)
715 if (bDragMode
== FALSE
)
718 pt
.x
= (short)LOWORD(lParam
); // horizontal position of cursor
719 pt
.y
= (short)HIWORD(lParam
);
721 GetClientRect(hwnd
, &clientrect
);
722 GetWindowRect(hwnd
, &rect
);
724 ClientToScreen(hwnd
, &zero
);
725 OffsetRect(&clientrect
, zero
.x
-rect
.left
, zero
.y
-rect
.top
);
727 //convert the mouse coordinates relative to the top-left of
729 ClientToScreen(hwnd
, &pt
);
733 //same for the window coordinates - make them relative to 0,0
734 OffsetRect(&rect
, -rect
.left
, -rect
.top
);
738 if (pt
.x
> rect
.right
-4)
742 if (pt
.y
> rect
.bottom
-4)
743 pt
.y
= rect
.bottom
-4;
745 if ((wParam
& MK_LBUTTON
) && ((bVertical
&& (pt
.y
!= oldy
)) || (!bVertical
&& (pt
.x
!= oldx
))))
747 hdc
= GetWindowDC(hwnd
);
751 DrawXorBar(hdc
, clientrect
.left
, oldy
+2, clientrect
.right
-clientrect
.left
-2, 4);
752 DrawXorBar(hdc
, clientrect
.left
, pt
.y
+2, clientrect
.right
-clientrect
.left
-2, 4);
756 DrawXorBar(hdc
, oldx
+2, clientrect
.top
, 4, clientrect
.bottom
-clientrect
.top
-2);
757 DrawXorBar(hdc
, pt
.x
+2, clientrect
.top
, 4, clientrect
.bottom
-clientrect
.top
-2);
760 ReleaseDC(hwnd
, hdc
);
769 bool CMainWindow::OpenDialog()
771 return (DialogBox(hResource
, MAKEINTRESOURCE(IDD_OPEN
), *this, (DLGPROC
)OpenDlgProc
)==IDOK
);
774 BOOL CALLBACK
CMainWindow::OpenDlgProc(HWND hwndDlg
, UINT message
, WPARAM wParam
, LPARAM lParam
)
780 // center on the parent window
781 HWND hParentWnd
= ::GetParent(hwndDlg
);
782 RECT parentrect
, childrect
, centeredrect
;
783 GetWindowRect(hParentWnd
, &parentrect
);
784 GetWindowRect(hwndDlg
, &childrect
);
785 centeredrect
.left
= parentrect
.left
+ ((parentrect
.right
-parentrect
.left
-childrect
.right
+childrect
.left
)/2);
786 centeredrect
.right
= centeredrect
.left
+ (childrect
.right
-childrect
.left
);
787 centeredrect
.top
= parentrect
.top
+ ((parentrect
.bottom
-parentrect
.top
-childrect
.bottom
+childrect
.top
)/2);
788 centeredrect
.bottom
= centeredrect
.top
+ (childrect
.bottom
-childrect
.top
);
789 SetWindowPos(hwndDlg
, NULL
, centeredrect
.left
, centeredrect
.top
, centeredrect
.right
-centeredrect
.left
, centeredrect
.bottom
-centeredrect
.top
, SWP_SHOWWINDOW
);
794 switch (LOWORD(wParam
))
798 TCHAR path
[MAX_PATH
] = {0};
799 if (AskForFile(hwndDlg
, path
))
801 SetDlgItemText(hwndDlg
, IDC_LEFTIMAGE
, path
);
805 case IDC_RIGHTBROWSE
:
807 TCHAR path
[MAX_PATH
] = {0};
808 if (AskForFile(hwndDlg
, path
))
810 SetDlgItemText(hwndDlg
, IDC_RIGHTIMAGE
, path
);
816 TCHAR path
[MAX_PATH
];
817 if (!GetDlgItemText(hwndDlg
, IDC_LEFTIMAGE
, path
, MAX_PATH
))
820 if (!GetDlgItemText(hwndDlg
, IDC_RIGHTIMAGE
, path
, MAX_PATH
))
826 EndDialog(hwndDlg
, wParam
);
833 bool CMainWindow::AskForFile(HWND owner
, TCHAR
* path
)
835 OPENFILENAME ofn
= {0}; // common dialog box structure
836 // Initialize OPENFILENAME
837 ofn
.lStructSize
= sizeof(OPENFILENAME
);
838 ofn
.hwndOwner
= owner
;
839 ofn
.lpstrFile
= path
;
840 ofn
.nMaxFile
= MAX_PATH
;
841 ofn
.lpstrTitle
= ResString(::hResource
, IDS_OPENIMAGEFILE
);
842 ofn
.Flags
= OFN_DONTADDTORECENT
| OFN_FILEMUSTEXIST
| OFN_EXPLORER
;
843 ofn
.hInstance
= ::hResource
;
844 TCHAR filters
[] = _T("Images\0*.wmf;*.jpg;*jpeg;*.bmp;*.gif;*.png;*.ico;*.dib;*.emf\0All (*.*)\0*.*\0\0");
845 ofn
.lpstrFilter
= filters
;
846 ofn
.nFilterIndex
= 1;
847 // Display the Open dialog box.
848 if (GetOpenFileName(&ofn
)==FALSE
)
855 bool CMainWindow::CreateToolbar()
857 // Ensure that the common control DLL is loaded.
858 INITCOMMONCONTROLSEX icex
;
859 icex
.dwSize
= sizeof(INITCOMMONCONTROLSEX
);
860 icex
.dwICC
= ICC_BAR_CLASSES
| ICC_WIN95_CLASSES
;
861 InitCommonControlsEx(&icex
);
863 hwndTB
= CreateWindowEx(0,
866 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| TBSTYLE_FLAT
| TBSTYLE_TOOLTIPS
,
869 (HMENU
)IDC_TORTOISEIDIFF
,
872 if (hwndTB
== INVALID_HANDLE_VALUE
)
875 SendMessage(hwndTB
, TB_BUTTONSTRUCTSIZE
, (WPARAM
) sizeof(TBBUTTON
), 0);
878 // create an imagelist containing the icons for the toolbar
879 hToolbarImgList
= ImageList_Create(24, 24, ILC_COLOR32
| ILC_MASK
, 12, 4);
880 if (hToolbarImgList
== NULL
)
883 HICON hIcon
= LoadIcon(hResource
, MAKEINTRESOURCE(IDI_OVERLAP
));
884 tbb
[index
].iBitmap
= ImageList_AddIcon(hToolbarImgList
, hIcon
);
885 tbb
[index
].idCommand
= ID_VIEW_OVERLAPIMAGES
;
886 tbb
[index
].fsState
= TBSTATE_ENABLED
;
887 tbb
[index
].fsStyle
= BTNS_BUTTON
;
888 tbb
[index
].dwData
= 0;
889 tbb
[index
++].iString
= 0;
891 hIcon
= LoadIcon(hResource
, MAKEINTRESOURCE(IDI_BLEND
));
892 tbb
[index
].iBitmap
= ImageList_AddIcon(hToolbarImgList
, hIcon
);
893 tbb
[index
].idCommand
= ID_VIEW_BLENDALPHA
;
894 tbb
[index
].fsState
= 0;
895 tbb
[index
].fsStyle
= BTNS_BUTTON
;
896 tbb
[index
].dwData
= 0;
897 tbb
[index
++].iString
= 0;
899 hIcon
= LoadIcon(hResource
, MAKEINTRESOURCE(IDI_LINK
));
900 tbb
[index
].iBitmap
= ImageList_AddIcon(hToolbarImgList
, hIcon
);
901 tbb
[index
].idCommand
= ID_VIEW_LINKIMAGESTOGETHER
;
902 tbb
[index
].fsState
= TBSTATE_ENABLED
| TBSTATE_CHECKED
;
903 tbb
[index
].fsStyle
= BTNS_BUTTON
;
904 tbb
[index
].dwData
= 0;
905 tbb
[index
++].iString
= 0;
907 hIcon
= LoadIcon(hResource
, MAKEINTRESOURCE(IDI_FITTOGETHER
));
908 tbb
[index
].iBitmap
= ImageList_AddIcon(hToolbarImgList
, hIcon
);
909 tbb
[index
].idCommand
= ID_VIEW_FITTOGETHER
;
910 tbb
[index
].fsState
= TBSTATE_ENABLED
;
911 tbb
[index
].fsStyle
= BTNS_BUTTON
;
912 tbb
[index
].dwData
= 0;
913 tbb
[index
++].iString
= 0;
915 tbb
[index
].iBitmap
= 0;
916 tbb
[index
].idCommand
= 0;
917 tbb
[index
].fsState
= TBSTATE_ENABLED
;
918 tbb
[index
].fsStyle
= BTNS_SEP
;
919 tbb
[index
].dwData
= 0;
920 tbb
[index
++].iString
= 0;
922 hIcon
= LoadIcon(hResource
, MAKEINTRESOURCE(IDI_VERTICAL
));
923 tbb
[index
].iBitmap
= ImageList_AddIcon(hToolbarImgList
, hIcon
);
924 tbb
[index
].idCommand
= ID_VIEW_ARRANGEVERTICAL
;
925 tbb
[index
].fsState
= TBSTATE_ENABLED
;
926 tbb
[index
].fsStyle
= BTNS_BUTTON
;
927 tbb
[index
].dwData
= 0;
928 tbb
[index
++].iString
= 0;
930 hIcon
= LoadIcon(hResource
, MAKEINTRESOURCE(IDI_FITINWINDOW
));
931 tbb
[index
].iBitmap
= ImageList_AddIcon(hToolbarImgList
, hIcon
);
932 tbb
[index
].idCommand
= ID_VIEW_FITIMAGESINWINDOW
;
933 tbb
[index
].fsState
= TBSTATE_ENABLED
;
934 tbb
[index
].fsStyle
= BTNS_BUTTON
;
935 tbb
[index
].dwData
= 0;
936 tbb
[index
++].iString
= 0;
938 hIcon
= LoadIcon(hResource
, MAKEINTRESOURCE(IDI_ORIGSIZE
));
939 tbb
[index
].iBitmap
= ImageList_AddIcon(hToolbarImgList
, hIcon
);
940 tbb
[index
].idCommand
= ID_VIEW_ORININALSIZE
;
941 tbb
[index
].fsState
= TBSTATE_ENABLED
;
942 tbb
[index
].fsStyle
= BTNS_BUTTON
;
943 tbb
[index
].dwData
= 0;
944 tbb
[index
++].iString
= 0;
946 hIcon
= LoadIcon(hResource
, MAKEINTRESOURCE(IDI_ZOOMIN
));
947 tbb
[index
].iBitmap
= ImageList_AddIcon(hToolbarImgList
, hIcon
);
948 tbb
[index
].idCommand
= ID_VIEW_ZOOMIN
;
949 tbb
[index
].fsState
= TBSTATE_ENABLED
;
950 tbb
[index
].fsStyle
= BTNS_BUTTON
;
951 tbb
[index
].dwData
= 0;
952 tbb
[index
++].iString
= 0;
954 hIcon
= LoadIcon(hResource
, MAKEINTRESOURCE(IDI_ZOOMOUT
));
955 tbb
[index
].iBitmap
= ImageList_AddIcon(hToolbarImgList
, hIcon
);
956 tbb
[index
].idCommand
= ID_VIEW_ZOOMOUT
;
957 tbb
[index
].fsState
= TBSTATE_ENABLED
;
958 tbb
[index
].fsStyle
= BTNS_BUTTON
;
959 tbb
[index
].dwData
= 0;
960 tbb
[index
++].iString
= 0;
962 tbb
[index
].iBitmap
= 0;
963 tbb
[index
].idCommand
= 0;
964 tbb
[index
].fsState
= TBSTATE_ENABLED
;
965 tbb
[index
].fsStyle
= BTNS_SEP
;
966 tbb
[index
].dwData
= 0;
967 tbb
[index
++].iString
= 0;
969 hIcon
= LoadIcon(hResource
, MAKEINTRESOURCE(IDI_IMGINFO
));
970 tbb
[index
].iBitmap
= ImageList_AddIcon(hToolbarImgList
, hIcon
);
971 tbb
[index
].idCommand
= ID_VIEW_IMAGEINFO
;
972 tbb
[index
].fsState
= TBSTATE_ENABLED
;
973 tbb
[index
].fsStyle
= BTNS_BUTTON
;
974 tbb
[index
].dwData
= 0;
975 tbb
[index
++].iString
= 0;
977 SendMessage(hwndTB
, TB_SETIMAGELIST
, 0, (LPARAM
)hToolbarImgList
);
978 SendMessage(hwndTB
, TB_ADDBUTTONS
, (WPARAM
)index
, (LPARAM
) (LPTBBUTTON
) &tbb
);
979 SendMessage(hwndTB
, TB_AUTOSIZE
, 0, 0);
980 ShowWindow(hwndTB
, SW_SHOW
);