OSDN Git Service

Fixed issue #112: (8) Low hanging GUI fruits during Commit and Push
[tortoisegit/TortoiseGitJp.git] / src / TortoiseIDiff / MainWindow.cpp
1 // TortoiseIDiff - an image diff viewer in TortoiseSVN\r
2 \r
3 // Copyright (C) 2006 - 2009 - TortoiseSVN\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 #include "StdAfx.h"\r
20 #include "commctrl.h"\r
21 #include "Commdlg.h"\r
22 #include "TortoiseIDiff.h"\r
23 #include "MainWindow.h"\r
24 #include "AboutDlg.h"\r
25 \r
26 #pragma comment(lib, "comctl32.lib")\r
27 \r
28 tstring CMainWindow::leftpicpath;\r
29 tstring CMainWindow::leftpictitle;\r
30 \r
31 tstring CMainWindow::rightpicpath;\r
32 tstring CMainWindow::rightpictitle;\r
33 \r
34 bool CMainWindow::RegisterAndCreateWindow()\r
35 {\r
36         WNDCLASSEX wcx; \r
37 \r
38         // Fill in the window class structure with default parameters \r
39         wcx.cbSize = sizeof(WNDCLASSEX);\r
40         wcx.style = CS_HREDRAW | CS_VREDRAW;\r
41         wcx.lpfnWndProc = CWindow::stWinMsgHandler;\r
42         wcx.cbClsExtra = 0;\r
43         wcx.cbWndExtra = 0;\r
44         wcx.hInstance = hResource;\r
45         wcx.hCursor = LoadCursor(NULL, IDC_SIZEWE);\r
46         wcx.lpszClassName = ResString(hResource, IDS_APP_TITLE);\r
47         wcx.hIcon = LoadIcon(hResource, MAKEINTRESOURCE(IDI_TORTOISEIDIFF));\r
48         wcx.hbrBackground = (HBRUSH)(COLOR_3DFACE+1);\r
49         wcx.lpszMenuName = MAKEINTRESOURCE(IDC_TORTOISEIDIFF);\r
50         wcx.hIconSm     = LoadIcon(wcx.hInstance, MAKEINTRESOURCE(IDI_TORTOISEIDIFF));\r
51         if (RegisterWindow(&wcx))\r
52         {\r
53                 if (Create(WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_VISIBLE, NULL))\r
54                 {\r
55                         ShowWindow(m_hwnd, SW_SHOW);\r
56                         UpdateWindow(m_hwnd);\r
57                         return true;\r
58                 }\r
59         }\r
60         return false;\r
61 }\r
62 \r
63 void CMainWindow::PositionChildren(RECT * clientrect /* = NULL */)\r
64 {\r
65         RECT tbRect;\r
66         if (clientrect == NULL)\r
67                 return;\r
68         SendMessage(hwndTB, TB_AUTOSIZE, 0, 0);\r
69         GetWindowRect(hwndTB, &tbRect);\r
70         LONG tbHeight = tbRect.bottom-tbRect.top-1;\r
71         HDWP hdwp = BeginDeferWindowPos(2);\r
72         if (bOverlap)\r
73         {\r
74                 SetWindowPos(picWindow1, NULL, clientrect->left, clientrect->top+tbHeight, clientrect->right-clientrect->left, clientrect->bottom-clientrect->top-tbHeight, SWP_SHOWWINDOW);\r
75         }\r
76         else\r
77         {\r
78                 if (bVertical)\r
79                 {\r
80                         RECT child;\r
81                         child.left = clientrect->left;\r
82                         child.top = clientrect->top+tbHeight;\r
83                         child.right = clientrect->right;\r
84                         child.bottom = nSplitterPos-(SPLITTER_BORDER/2);\r
85                         if (hdwp) hdwp = DeferWindowPos(hdwp, picWindow1, NULL, child.left, child.top, child.right-child.left, child.bottom-child.top, SWP_FRAMECHANGED|SWP_SHOWWINDOW);\r
86                         child.top = nSplitterPos+(SPLITTER_BORDER/2);\r
87                         child.bottom = clientrect->bottom;\r
88                         if (hdwp) hdwp = DeferWindowPos(hdwp, picWindow2, NULL, child.left, child.top, child.right-child.left, child.bottom-child.top, SWP_FRAMECHANGED|SWP_SHOWWINDOW);\r
89                 }\r
90                 else\r
91                 {\r
92                         RECT child;\r
93                         child.left = clientrect->left;\r
94                         child.top = clientrect->top+tbHeight;\r
95                         child.right = nSplitterPos-(SPLITTER_BORDER/2);\r
96                         child.bottom = clientrect->bottom;\r
97                         if (hdwp) hdwp = DeferWindowPos(hdwp, picWindow1, NULL, child.left, child.top, child.right-child.left, child.bottom-child.top, SWP_FRAMECHANGED|SWP_SHOWWINDOW);\r
98                         child.left = nSplitterPos+(SPLITTER_BORDER/2);\r
99                         child.right = clientrect->right;\r
100                         if (hdwp) hdwp = DeferWindowPos(hdwp, picWindow2, NULL, child.left, child.top, child.right-child.left, child.bottom-child.top, SWP_FRAMECHANGED|SWP_SHOWWINDOW);\r
101                 }\r
102         }\r
103         if (hdwp) EndDeferWindowPos(hdwp);\r
104         picWindow1.SetTransparentColor(transparentColor);\r
105         picWindow2.SetTransparentColor(transparentColor);\r
106         InvalidateRect(*this, NULL, FALSE);\r
107 }\r
108 \r
109 LRESULT CALLBACK CMainWindow::WinMsgHandler(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)\r
110 {\r
111         switch (uMsg)\r
112         {\r
113         case WM_CREATE:\r
114                 {\r
115                         m_hwnd = hwnd;\r
116                         picWindow1.RegisterAndCreateWindow(hwnd);\r
117                         picWindow1.SetPic(leftpicpath, leftpictitle, true);\r
118                         picWindow2.RegisterAndCreateWindow(hwnd);\r
119                         picWindow2.SetPic(rightpicpath, rightpictitle, false);\r
120 \r
121                         picWindow1.SetOtherPicWindow(&picWindow2);\r
122                         picWindow2.SetOtherPicWindow(&picWindow1);\r
123                         // center the splitter\r
124                         RECT rect;\r
125                         GetClientRect(hwnd, &rect);\r
126                         nSplitterPos = (rect.right-rect.left-SPLITTER_BORDER)/2;\r
127                         CreateToolbar();\r
128                         PositionChildren(&rect);\r
129                         picWindow1.FitImageInWindow();\r
130                         picWindow2.FitImageInWindow();\r
131                 }\r
132                 break;\r
133         case WM_COMMAND:\r
134                 {\r
135                         return DoCommand(LOWORD(wParam));\r
136                 }\r
137                 break;\r
138         case WM_PAINT:\r
139                 {\r
140                         PAINTSTRUCT ps;\r
141                         HDC hdc;\r
142                         RECT rect;\r
143 \r
144                         ::GetClientRect(*this, &rect);\r
145                         hdc = BeginPaint(hwnd, &ps);\r
146                         SetBkColor(hdc, GetSysColor(COLOR_3DFACE));\r
147                         ::ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);\r
148                         EndPaint(hwnd, &ps);\r
149                 }\r
150                 break;\r
151     case WM_GETMINMAXINFO:\r
152                 {\r
153                         MINMAXINFO * mmi = (MINMAXINFO*)lParam;\r
154                         mmi->ptMinTrackSize.x = WINDOW_MINWIDTH;\r
155                         mmi->ptMinTrackSize.y = WINDOW_MINHEIGHT;\r
156                         return 0;\r
157                 }\r
158                 break;\r
159         case WM_SIZE:\r
160                 {\r
161                         RECT rect;\r
162                         GetClientRect(hwnd, &rect);\r
163                         if (bVertical)\r
164                         {\r
165                                 RECT tbRect;\r
166                                 GetWindowRect(hwndTB, &tbRect);\r
167                                 LONG tbHeight = tbRect.bottom-tbRect.top-1;\r
168                                 nSplitterPos = (rect.bottom-rect.top-SPLITTER_BORDER+tbHeight)/2;\r
169                         }\r
170                         else\r
171                                 nSplitterPos = (rect.right-rect.left-SPLITTER_BORDER)/2;\r
172                         PositionChildren(&rect);\r
173                 }\r
174                 break;\r
175         case WM_SETCURSOR:\r
176                 {\r
177                         if ((HWND)wParam == *this)\r
178                         {\r
179                                 RECT rect;\r
180                                 POINT pt;\r
181                                 GetClientRect(*this, &rect);\r
182                                 GetCursorPos(&pt);\r
183                                 ScreenToClient(*this, &pt);\r
184                                 if (PtInRect(&rect, pt))\r
185                                 {\r
186                                         if (bVertical)\r
187                                         {\r
188                                                 HCURSOR hCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZENS));\r
189                                                 SetCursor(hCur);\r
190                                         }\r
191                                         else\r
192                                         {\r
193                                                 HCURSOR hCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZEWE));\r
194                                                 SetCursor(hCur);\r
195                                         }\r
196                                         return TRUE;\r
197                                 }\r
198                         }\r
199                         return DefWindowProc(hwnd, uMsg, wParam, lParam);\r
200                 }\r
201                 break;\r
202         case WM_LBUTTONDOWN:\r
203                 Splitter_OnLButtonDown(hwnd, uMsg, wParam, lParam);\r
204                 break;\r
205         case WM_LBUTTONUP:\r
206                 Splitter_OnLButtonUp(hwnd, uMsg, wParam, lParam);\r
207                 break;\r
208         case WM_MOUSEMOVE:\r
209                 Splitter_OnMouseMove(hwnd, uMsg, wParam, lParam);\r
210                 break;\r
211         case WM_MOUSEWHEEL:\r
212                 {\r
213                         // find out if the mouse cursor is over one of the views, and if\r
214                         // it is, pass the mouse wheel message to that view\r
215                         POINT pt;\r
216                         DWORD ptW = GetMessagePos();\r
217                         pt.x = GET_X_LPARAM(ptW);\r
218                         pt.y = GET_Y_LPARAM(ptW);\r
219                         RECT rect;\r
220                         GetWindowRect(picWindow1, &rect);\r
221                         if (PtInRect(&rect, pt))\r
222                         {\r
223                                 picWindow1.OnMouseWheel(GET_KEYSTATE_WPARAM(wParam), GET_WHEEL_DELTA_WPARAM(wParam));\r
224                         }\r
225                         else\r
226                         {\r
227                                 GetWindowRect(picWindow2, &rect);\r
228                                 if (PtInRect(&rect, pt))\r
229                                 {\r
230                                         picWindow2.OnMouseWheel(GET_KEYSTATE_WPARAM(wParam), GET_WHEEL_DELTA_WPARAM(wParam));\r
231                                 }\r
232                         }\r
233                 }\r
234                 break;\r
235         case WM_MOUSEHWHEEL:\r
236                 {\r
237                         // find out if the mouse cursor is over one of the views, and if\r
238                         // it is, pass the mouse wheel message to that view\r
239                         POINT pt;\r
240                         DWORD ptW = GetMessagePos();\r
241                         pt.x = GET_X_LPARAM(ptW);\r
242                         pt.y = GET_Y_LPARAM(ptW);\r
243                         RECT rect;\r
244                         GetWindowRect(picWindow1, &rect);\r
245                         if (PtInRect(&rect, pt))\r
246                         {\r
247                                 picWindow1.OnMouseWheel(GET_KEYSTATE_WPARAM(wParam)|MK_SHIFT, GET_WHEEL_DELTA_WPARAM(wParam));\r
248                         }\r
249                         else\r
250                         {\r
251                                 GetWindowRect(picWindow2, &rect);\r
252                                 if (PtInRect(&rect, pt))\r
253                                 {\r
254                                         picWindow2.OnMouseWheel(GET_KEYSTATE_WPARAM(wParam)|MK_SHIFT, GET_WHEEL_DELTA_WPARAM(wParam));\r
255                                 }\r
256                         }\r
257                 }\r
258                 break;\r
259         case WM_NOTIFY:\r
260                 {\r
261                         LPNMHDR pNMHDR = (LPNMHDR)lParam;\r
262                         if (pNMHDR->code == TTN_GETDISPINFO)\r
263                         {\r
264                                 LPTOOLTIPTEXT lpttt; \r
265 \r
266                                 lpttt = (LPTOOLTIPTEXT) lParam; \r
267                                 lpttt->hinst = hResource; \r
268 \r
269                                 // Specify the resource identifier of the descriptive \r
270                                 // text for the given button. \r
271                                 TCHAR stringbuf[MAX_PATH] = {0};\r
272                                 MENUITEMINFO mii;\r
273                                 mii.cbSize = sizeof(MENUITEMINFO);\r
274                                 mii.fMask = MIIM_TYPE;\r
275                                 mii.dwTypeData = stringbuf;\r
276                                 mii.cch = sizeof(stringbuf)/sizeof(TCHAR);\r
277                                 GetMenuItemInfo(GetMenu(*this), (UINT)lpttt->hdr.idFrom, FALSE, &mii);\r
278                                 lpttt->lpszText = stringbuf;\r
279                         }\r
280                 }\r
281                 break;\r
282         case WM_DESTROY:\r
283                 bWindowClosed = TRUE;\r
284                 PostQuitMessage(0);\r
285                 break;\r
286         case WM_CLOSE:\r
287                 ImageList_Destroy(hToolbarImgList);\r
288                 ::DestroyWindow(m_hwnd);\r
289                 break;\r
290         default:\r
291                 return DefWindowProc(hwnd, uMsg, wParam, lParam);\r
292         }\r
293 \r
294         return 0;\r
295 };\r
296 \r
297 LRESULT CMainWindow::DoCommand(int id)\r
298 {\r
299         switch (id) \r
300         {\r
301         case ID_FILE_OPEN:\r
302                 {\r
303                         if (OpenDialog())\r
304                         {\r
305                                 picWindow1.SetPic(leftpicpath, _T(""), true);\r
306                                 picWindow2.SetPic(rightpicpath, _T(""), false);\r
307                                 if (bOverlap)\r
308                                 {\r
309                                         picWindow1.SetSecondPic(picWindow2.GetPic(), rightpictitle, rightpicpath);\r
310                                 }\r
311                                 else\r
312                                 {\r
313                                         picWindow1.SetSecondPic();\r
314                                 }\r
315                                 RECT rect;\r
316                                 GetClientRect(*this, &rect);\r
317                                 PositionChildren(&rect);\r
318                                 picWindow1.FitImageInWindow();\r
319                                 picWindow2.FitImageInWindow();\r
320                         }\r
321                 }\r
322                 break;\r
323         case ID_VIEW_IMAGEINFO:\r
324                 {\r
325                         bShowInfo = !bShowInfo;\r
326                         HMENU hMenu = GetMenu(*this);\r
327                         UINT uCheck = MF_BYCOMMAND;\r
328                         uCheck |= bShowInfo ? MF_CHECKED : MF_UNCHECKED;\r
329                         CheckMenuItem(hMenu, ID_VIEW_IMAGEINFO, uCheck);\r
330 \r
331                         picWindow1.ShowInfo(bShowInfo);\r
332                         picWindow2.ShowInfo(bShowInfo);\r
333 \r
334                         // change the state of the toolbar button\r
335                         TBBUTTONINFO tbi;\r
336                         tbi.cbSize = sizeof(TBBUTTONINFO);\r
337                         tbi.dwMask = TBIF_STATE;\r
338                         tbi.fsState = bShowInfo ? TBSTATE_CHECKED | TBSTATE_ENABLED : TBSTATE_ENABLED;\r
339                         SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_IMAGEINFO, (LPARAM)&tbi);\r
340                 }\r
341                 break;\r
342         case ID_VIEW_OVERLAPIMAGES:\r
343                 {\r
344                         bOverlap = !bOverlap;\r
345                         HMENU hMenu = GetMenu(*this);\r
346                         UINT uCheck = MF_BYCOMMAND;\r
347                         uCheck |= bOverlap ? MF_CHECKED : MF_UNCHECKED;\r
348                         CheckMenuItem(hMenu, ID_VIEW_OVERLAPIMAGES, uCheck);\r
349                         uCheck |= (m_BlendType == CPicWindow::BLEND_ALPHA) ? MF_CHECKED : MF_UNCHECKED;\r
350                         CheckMenuItem(hMenu, ID_VIEW_BLENDALPHA, uCheck);\r
351 \r
352                         // change the state of the toolbar button\r
353                         TBBUTTONINFO tbi;\r
354                         tbi.cbSize = sizeof(TBBUTTONINFO);\r
355                         tbi.dwMask = TBIF_STATE;\r
356                         tbi.fsState = bOverlap ? TBSTATE_CHECKED | TBSTATE_ENABLED : TBSTATE_ENABLED;\r
357                         SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_OVERLAPIMAGES, (LPARAM)&tbi);\r
358 \r
359                         tbi.fsState = (m_BlendType == CPicWindow::BLEND_ALPHA) ? TBSTATE_CHECKED : 0;\r
360                         if (bOverlap)\r
361                                 tbi.fsState |= TBSTATE_ENABLED;\r
362                         else\r
363                                 tbi.fsState = 0;\r
364                         SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_BLENDALPHA, (LPARAM)&tbi);\r
365 \r
366                         if (bOverlap)\r
367                                 tbi.fsState = 0;\r
368                         else\r
369                                 tbi.fsState = bVertical ? TBSTATE_ENABLED | TBSTATE_CHECKED : TBSTATE_ENABLED;\r
370                         SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_ARRANGEVERTICAL, (LPARAM)&tbi);\r
371 \r
372                         ShowWindow(picWindow2, bOverlap ? SW_HIDE : SW_SHOW);\r
373 \r
374                         if (bOverlap)\r
375                         {\r
376                                 picWindow1.StopTimer();\r
377                                 picWindow2.StopTimer();\r
378                                 picWindow1.SetSecondPic(picWindow2.GetPic(), rightpictitle, rightpicpath, \r
379                                         picWindow2.GetHPos(), picWindow2.GetVPos());\r
380                                 picWindow1.SetBlendAlpha(m_BlendType, 0.5f);\r
381                         }\r
382                         else\r
383                         {\r
384                                 picWindow1.SetSecondPic();\r
385                         }\r
386 \r
387 \r
388                         RECT rect;\r
389                         GetClientRect(*this, &rect);\r
390                         PositionChildren(&rect);\r
391 \r
392                         if ((bFitSizes)&&(bOverlap))\r
393                         {\r
394                                 picWindow1.FitSizes(bFitSizes);\r
395                         }\r
396             return 0;\r
397                 }\r
398                 break;\r
399         case ID_VIEW_BLENDALPHA:\r
400                 {\r
401                         if (m_BlendType == CPicWindow::BLEND_ALPHA)\r
402                                 m_BlendType = CPicWindow::BLEND_XOR;\r
403                         else\r
404                                 m_BlendType = CPicWindow::BLEND_ALPHA;\r
405 \r
406                         HMENU hMenu = GetMenu(*this);\r
407                         UINT uCheck = MF_BYCOMMAND;\r
408                         uCheck |= (m_BlendType == CPicWindow::BLEND_ALPHA) ? MF_CHECKED : MF_UNCHECKED;\r
409                         CheckMenuItem(hMenu, ID_VIEW_BLENDALPHA, uCheck);\r
410 \r
411                         // change the state of the toolbar button\r
412                         TBBUTTONINFO tbi;\r
413                         tbi.cbSize = sizeof(TBBUTTONINFO);\r
414                         tbi.dwMask = TBIF_STATE;\r
415                         tbi.fsState = (m_BlendType == CPicWindow::BLEND_ALPHA) ? TBSTATE_CHECKED | TBSTATE_ENABLED : TBSTATE_ENABLED;\r
416                         SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_BLENDALPHA, (LPARAM)&tbi);\r
417                         picWindow1.SetBlendAlpha(m_BlendType, picWindow1.GetBlendAlpha());\r
418                         PositionChildren();\r
419                 }\r
420                 break;\r
421         case ID_VIEW_TRANSPARENTCOLOR:\r
422                 {\r
423                         static COLORREF customColors[16] = {0};\r
424                         CHOOSECOLOR ccDlg;\r
425                         memset(&ccDlg, 0, sizeof(ccDlg));\r
426                         ccDlg.lStructSize = sizeof(ccDlg);\r
427                         ccDlg.hwndOwner = m_hwnd;\r
428                         ccDlg.rgbResult = transparentColor;\r
429                         ccDlg.lpCustColors = customColors;\r
430                         ccDlg.Flags = CC_RGBINIT | CC_FULLOPEN;\r
431                         if(ChooseColor(&ccDlg))\r
432                         {\r
433                                 transparentColor = ccDlg.rgbResult;\r
434                                 picWindow1.SetTransparentColor(transparentColor);\r
435                                 picWindow2.SetTransparentColor(transparentColor);\r
436                                 // The color picker takes the focus and we don't get it back.\r
437                                 ::SetFocus(picWindow1);\r
438                         }\r
439                 }\r
440                 break;\r
441         case ID_VIEW_FITTOGETHER:\r
442                 {\r
443                         bFitSizes = !bFitSizes;\r
444                         picWindow1.FitSizes(bFitSizes);\r
445                         picWindow2.FitSizes(bFitSizes);\r
446 \r
447                         HMENU hMenu = GetMenu(*this);\r
448                         UINT uCheck = MF_BYCOMMAND;\r
449                         uCheck |= bFitSizes ? MF_CHECKED : MF_UNCHECKED;\r
450                         CheckMenuItem(hMenu, ID_VIEW_FITTOGETHER, uCheck);\r
451 \r
452                         // change the state of the toolbar button\r
453                         TBBUTTONINFO tbi;\r
454                         tbi.cbSize = sizeof(TBBUTTONINFO);\r
455                         tbi.dwMask = TBIF_STATE;\r
456                         tbi.fsState = bFitSizes ? TBSTATE_CHECKED | TBSTATE_ENABLED : TBSTATE_ENABLED;\r
457                         SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_FITTOGETHER, (LPARAM)&tbi);\r
458                 }\r
459                 break;\r
460         case ID_VIEW_LINKIMAGESTOGETHER:\r
461                 {\r
462                         bLinkedPositions = !bLinkedPositions;\r
463                         picWindow1.LinkPositions(bLinkedPositions);\r
464                         picWindow2.LinkPositions(bLinkedPositions);\r
465 \r
466                         HMENU hMenu = GetMenu(*this);\r
467                         UINT uCheck = MF_BYCOMMAND;\r
468                         uCheck |= bLinkedPositions ? MF_CHECKED : MF_UNCHECKED;\r
469                         CheckMenuItem(hMenu, ID_VIEW_LINKIMAGESTOGETHER, uCheck);\r
470 \r
471                         // change the state of the toolbar button\r
472                         TBBUTTONINFO tbi;\r
473                         tbi.cbSize = sizeof(TBBUTTONINFO);\r
474                         tbi.dwMask = TBIF_STATE;\r
475                         tbi.fsState = bLinkedPositions ? TBSTATE_CHECKED | TBSTATE_ENABLED : TBSTATE_ENABLED;\r
476                         SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_LINKIMAGESTOGETHER, (LPARAM)&tbi);\r
477                 }\r
478                 break;\r
479         case ID_VIEW_ALPHA0:\r
480                 picWindow1.SetBlendAlpha(m_BlendType, 0.0f);\r
481                 break;\r
482         case ID_VIEW_ALPHA255:\r
483                 picWindow1.SetBlendAlpha(m_BlendType, 1.0f);\r
484                 break;\r
485         case ID_VIEW_ALPHA127:\r
486                 picWindow1.SetBlendAlpha(m_BlendType, 0.5f);\r
487                 break;\r
488         case ID_VIEW_ALPHATOGGLE:\r
489                 picWindow1.ToggleAlpha();\r
490                 break;\r
491         case ID_VIEW_FITIMAGESINWINDOW:\r
492                 {\r
493                         picWindow1.FitImageInWindow();\r
494                         picWindow2.FitImageInWindow();\r
495                 }\r
496                 break;\r
497         case ID_VIEW_ORININALSIZE:\r
498                 {\r
499                         picWindow1.SetZoom(1.0, false);\r
500                         picWindow2.SetZoom(1.0, false);\r
501                 }\r
502                 break;\r
503         case ID_VIEW_ZOOMIN:\r
504                 {\r
505                         picWindow1.Zoom(true, false);\r
506                         if (!bFitSizes)\r
507                                 picWindow2.Zoom(true, false);\r
508                 }\r
509                 break;\r
510         case ID_VIEW_ZOOMOUT:\r
511                 {\r
512                         picWindow1.Zoom(false, false);\r
513                         if (!bFitSizes)\r
514                                 picWindow2.Zoom(false, false);\r
515                 }\r
516                 break;\r
517         case ID_VIEW_ARRANGEVERTICAL:\r
518                 {\r
519                         bVertical = !bVertical;\r
520                         RECT rect;\r
521                         GetClientRect(*this, &rect);\r
522                         if (bVertical)\r
523                         {\r
524                                 RECT tbRect;\r
525                                 GetWindowRect(hwndTB, &tbRect);\r
526                                 LONG tbHeight = tbRect.bottom-tbRect.top-1;\r
527                                 nSplitterPos = (rect.bottom-rect.top-SPLITTER_BORDER+tbHeight)/2;\r
528                         }\r
529                         else\r
530                         {\r
531                                 nSplitterPos = (rect.right-rect.left-SPLITTER_BORDER)/2;\r
532                         }\r
533                         HMENU hMenu = GetMenu(*this);\r
534                         UINT uCheck = MF_BYCOMMAND;\r
535                         uCheck |= bVertical ? MF_CHECKED : MF_UNCHECKED;\r
536                         CheckMenuItem(hMenu, ID_VIEW_ARRANGEVERTICAL, uCheck);\r
537                         // change the state of the toolbar button\r
538                         TBBUTTONINFO tbi;\r
539                         tbi.cbSize = sizeof(TBBUTTONINFO);\r
540                         tbi.dwMask = TBIF_STATE;\r
541                         tbi.fsState = bVertical ? TBSTATE_CHECKED | TBSTATE_ENABLED : TBSTATE_ENABLED;\r
542                         SendMessage(hwndTB, TB_SETBUTTONINFO, ID_VIEW_ARRANGEVERTICAL, (LPARAM)&tbi);\r
543 \r
544                         PositionChildren(&rect);\r
545                 }\r
546                 break;\r
547         case ID_ABOUT:\r
548                 {\r
549                         CAboutDlg dlg(*this);\r
550                         dlg.DoModal(hInst, IDD_ABOUT, *this);\r
551                 }\r
552                 break;\r
553         case IDM_EXIT:\r
554                 ::PostQuitMessage(0);\r
555                 return 0;\r
556                 break;\r
557         default:\r
558                 break;\r
559         };\r
560         return 1;\r
561 }\r
562 \r
563 // splitter stuff\r
564 void CMainWindow::DrawXorBar(HDC hdc, int x1, int y1, int width, int height)\r
565 {\r
566         static WORD _dotPatternBmp[8] = \r
567         { \r
568                 0x0055, 0x00aa, 0x0055, 0x00aa, \r
569                 0x0055, 0x00aa, 0x0055, 0x00aa\r
570         };\r
571 \r
572         HBITMAP hbm;\r
573         HBRUSH  hbr, hbrushOld;\r
574 \r
575         hbm = CreateBitmap(8, 8, 1, 1, _dotPatternBmp);\r
576         hbr = CreatePatternBrush(hbm);\r
577 \r
578         SetBrushOrgEx(hdc, x1, y1, 0);\r
579         hbrushOld = (HBRUSH)SelectObject(hdc, hbr);\r
580 \r
581         PatBlt(hdc, x1, y1, width, height, PATINVERT);\r
582 \r
583         SelectObject(hdc, hbrushOld);\r
584 \r
585         DeleteObject(hbr);\r
586         DeleteObject(hbm);\r
587 }\r
588 \r
589 LRESULT CMainWindow::Splitter_OnLButtonDown(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)\r
590 {\r
591         POINT pt;\r
592         HDC hdc;\r
593         RECT rect;\r
594         RECT clientrect;\r
595 \r
596         pt.x = (short)LOWORD(lParam);  // horizontal position of cursor \r
597         pt.y = (short)HIWORD(lParam);\r
598 \r
599         GetClientRect(hwnd, &clientrect);\r
600         GetWindowRect(hwnd, &rect);\r
601         POINT zero = {0,0};\r
602         ClientToScreen(hwnd, &zero);\r
603         OffsetRect(&clientrect, zero.x-rect.left, zero.y-rect.top);\r
604 \r
605         //convert the mouse coordinates relative to the top-left of\r
606         //the window\r
607         ClientToScreen(hwnd, &pt);\r
608         pt.x -= rect.left;\r
609         pt.y -= rect.top;\r
610 \r
611         //same for the window coordinates - make them relative to 0,0\r
612         OffsetRect(&rect, -rect.left, -rect.top);\r
613 \r
614         if (pt.x < 0)\r
615                 pt.x = 0;\r
616         if (pt.x > rect.right-4) \r
617                 pt.x = rect.right-4;\r
618         if (pt.y < 0)\r
619                 pt.y = 0;\r
620         if (pt.y > rect.bottom-4)\r
621                 pt.y = rect.bottom-4;\r
622 \r
623         bDragMode = true;\r
624 \r
625         SetCapture(hwnd);\r
626 \r
627         hdc = GetWindowDC(hwnd);\r
628         if (bVertical)\r
629                 DrawXorBar(hdc, clientrect.left, pt.y+2, clientrect.right-clientrect.left-2, 4);\r
630         else\r
631                 DrawXorBar(hdc, pt.x+2, clientrect.top, 4, clientrect.bottom-clientrect.top-2);\r
632         ReleaseDC(hwnd, hdc);\r
633 \r
634         oldx = pt.x;\r
635         oldy = pt.y;\r
636 \r
637         return 0;\r
638 }\r
639 \r
640 \r
641 LRESULT CMainWindow::Splitter_OnLButtonUp(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)\r
642 {\r
643         HDC hdc;\r
644         RECT rect;\r
645         RECT clientrect;\r
646 \r
647         POINT pt;\r
648         pt.x = (short)LOWORD(lParam);  // horizontal position of cursor \r
649         pt.y = (short)HIWORD(lParam);\r
650 \r
651         if (bDragMode == FALSE)\r
652                 return 0;\r
653 \r
654         GetClientRect(hwnd, &clientrect);\r
655         GetWindowRect(hwnd, &rect);\r
656         POINT zero = {0,0};\r
657         ClientToScreen(hwnd, &zero);\r
658         OffsetRect(&clientrect, zero.x-rect.left, zero.y-rect.top);\r
659 \r
660         ClientToScreen(hwnd, &pt);\r
661         pt.x -= rect.left;\r
662         pt.y -= rect.top;\r
663 \r
664         OffsetRect(&rect, -rect.left, -rect.top);\r
665 \r
666         if (pt.x < 0)\r
667                 pt.x = 0;\r
668         if (pt.x > rect.right-4) \r
669                 pt.x = rect.right-4;\r
670         if (pt.y < 0)\r
671                 pt.y = 0;\r
672         if (pt.y > rect.bottom-4)\r
673                 pt.y = rect.bottom-4;\r
674 \r
675         hdc = GetWindowDC(hwnd);\r
676         if (bVertical)\r
677                 DrawXorBar(hdc, clientrect.left, oldy+2, clientrect.right-clientrect.left-2, 4);                        \r
678         else\r
679                 DrawXorBar(hdc, oldx+2, clientrect.top, 4, clientrect.bottom-clientrect.top-2);                 \r
680         ReleaseDC(hwnd, hdc);\r
681 \r
682         oldx = pt.x;\r
683         oldy = pt.y;\r
684 \r
685         bDragMode = false;\r
686 \r
687         //convert the splitter position back to screen coords.\r
688         GetWindowRect(hwnd, &rect);\r
689         pt.x += rect.left;\r
690         pt.y += rect.top;\r
691 \r
692         //now convert into CLIENT coordinates\r
693         ScreenToClient(hwnd, &pt);\r
694         GetClientRect(hwnd, &rect);\r
695         if (bVertical)\r
696                 nSplitterPos = pt.y;\r
697         else\r
698                 nSplitterPos = pt.x;\r
699 \r
700         ReleaseCapture();\r
701 \r
702         //position the child controls\r
703         PositionChildren(&rect);\r
704         return 0;\r
705 }\r
706 \r
707 LRESULT CMainWindow::Splitter_OnMouseMove(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)\r
708 {\r
709         HDC hdc;\r
710         RECT rect;\r
711         RECT clientrect;\r
712 \r
713         POINT pt;\r
714 \r
715         if (bDragMode == FALSE)\r
716                 return 0;\r
717 \r
718         pt.x = (short)LOWORD(lParam);  // horizontal position of cursor \r
719         pt.y = (short)HIWORD(lParam);\r
720 \r
721         GetClientRect(hwnd, &clientrect);\r
722         GetWindowRect(hwnd, &rect);\r
723         POINT zero = {0,0};\r
724         ClientToScreen(hwnd, &zero);\r
725         OffsetRect(&clientrect, zero.x-rect.left, zero.y-rect.top);\r
726 \r
727         //convert the mouse coordinates relative to the top-left of\r
728         //the window\r
729         ClientToScreen(hwnd, &pt);\r
730         pt.x -= rect.left;\r
731         pt.y -= rect.top;\r
732 \r
733         //same for the window coordinates - make them relative to 0,0\r
734         OffsetRect(&rect, -rect.left, -rect.top);\r
735 \r
736         if (pt.x < 0)\r
737                 pt.x = 0;\r
738         if (pt.x > rect.right-4) \r
739                 pt.x = rect.right-4;\r
740         if (pt.y < 0)\r
741                 pt.y = 0;\r
742         if (pt.y > rect.bottom-4)\r
743                 pt.y = rect.bottom-4;\r
744 \r
745         if ((wParam & MK_LBUTTON) && ((bVertical && (pt.y != oldy)) || (!bVertical && (pt.x != oldx))))\r
746         {\r
747                 hdc = GetWindowDC(hwnd);\r
748 \r
749                 if (bVertical)\r
750                 {\r
751                         DrawXorBar(hdc, clientrect.left, oldy+2, clientrect.right-clientrect.left-2, 4);\r
752                         DrawXorBar(hdc, clientrect.left, pt.y+2, clientrect.right-clientrect.left-2, 4);\r
753                 }\r
754                 else\r
755                 {\r
756                         DrawXorBar(hdc, oldx+2, clientrect.top, 4, clientrect.bottom-clientrect.top-2);\r
757                         DrawXorBar(hdc, pt.x+2, clientrect.top, 4, clientrect.bottom-clientrect.top-2);\r
758                 }\r
759 \r
760                 ReleaseDC(hwnd, hdc);\r
761 \r
762                 oldx = pt.x;\r
763                 oldy = pt.y;\r
764         }\r
765 \r
766         return 0;\r
767 }\r
768 \r
769 bool CMainWindow::OpenDialog()\r
770 {\r
771         return (DialogBox(hResource, MAKEINTRESOURCE(IDD_OPEN), *this, (DLGPROC)OpenDlgProc)==IDOK);\r
772 }\r
773 \r
774 BOOL CALLBACK CMainWindow::OpenDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
775 {\r
776         switch (message) \r
777         {\r
778         case WM_INITDIALOG:\r
779                 {\r
780                         // center on the parent window\r
781                         HWND hParentWnd = ::GetParent(hwndDlg);\r
782                         RECT parentrect, childrect, centeredrect;\r
783                         GetWindowRect(hParentWnd, &parentrect);\r
784                         GetWindowRect(hwndDlg, &childrect);\r
785                         centeredrect.left = parentrect.left + ((parentrect.right-parentrect.left-childrect.right+childrect.left)/2);\r
786                         centeredrect.right = centeredrect.left + (childrect.right-childrect.left);\r
787                         centeredrect.top = parentrect.top + ((parentrect.bottom-parentrect.top-childrect.bottom+childrect.top)/2);\r
788                         centeredrect.bottom = centeredrect.top + (childrect.bottom-childrect.top);\r
789                         SetWindowPos(hwndDlg, NULL, centeredrect.left, centeredrect.top, centeredrect.right-centeredrect.left, centeredrect.bottom-centeredrect.top, SWP_SHOWWINDOW);\r
790                         SetFocus(hwndDlg);\r
791                 }\r
792                 break;\r
793         case WM_COMMAND: \r
794                 switch (LOWORD(wParam)) \r
795                 {\r
796                 case IDC_LEFTBROWSE:\r
797                         {\r
798                                 TCHAR path[MAX_PATH] = {0};\r
799                                 if (AskForFile(hwndDlg, path))\r
800                                 {\r
801                                         SetDlgItemText(hwndDlg, IDC_LEFTIMAGE, path);\r
802                                 }\r
803                         }\r
804                         break;\r
805                 case IDC_RIGHTBROWSE:\r
806                         {\r
807                                 TCHAR path[MAX_PATH] = {0};\r
808                                 if (AskForFile(hwndDlg, path))\r
809                                 {\r
810                                         SetDlgItemText(hwndDlg, IDC_RIGHTIMAGE, path);\r
811                                 }\r
812                         }\r
813                         break;\r
814                 case IDOK: \r
815                         {\r
816                                 TCHAR path[MAX_PATH];\r
817                                 if (!GetDlgItemText(hwndDlg, IDC_LEFTIMAGE, path, MAX_PATH)) \r
818                                         *path = 0;\r
819                                 leftpicpath = path;\r
820                                 if (!GetDlgItemText(hwndDlg, IDC_RIGHTIMAGE, path, MAX_PATH))\r
821                                         *path = 0;\r
822                                 rightpicpath = path;\r
823                         }\r
824                         // Fall through. \r
825                 case IDCANCEL: \r
826                         EndDialog(hwndDlg, wParam); \r
827                         return TRUE; \r
828                 } \r
829         } \r
830         return FALSE; \r
831 }\r
832 \r
833 bool CMainWindow::AskForFile(HWND owner, TCHAR * path)\r
834 {\r
835         OPENFILENAME ofn = {0};                 // common dialog box structure\r
836         // Initialize OPENFILENAME\r
837         ofn.lStructSize = sizeof(OPENFILENAME);\r
838         ofn.hwndOwner = owner;\r
839         ofn.lpstrFile = path;\r
840         ofn.nMaxFile = MAX_PATH;\r
841         ofn.lpstrTitle = ResString(::hResource, IDS_OPENIMAGEFILE);\r
842         ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST | OFN_EXPLORER;\r
843         ofn.hInstance = ::hResource;\r
844         TCHAR filters[] = _T("Images\0*.wmf;*.jpg;*jpeg;*.bmp;*.gif;*.png;*.ico;*.dib;*.emf\0All (*.*)\0*.*\0\0");\r
845         ofn.lpstrFilter = filters;\r
846         ofn.nFilterIndex = 1;\r
847         // Display the Open dialog box. \r
848         if (GetOpenFileName(&ofn)==FALSE)\r
849         {\r
850                 return false;\r
851         }\r
852         return true;\r
853 }\r
854 \r
855 bool CMainWindow::CreateToolbar()\r
856 {\r
857         // Ensure that the common control DLL is loaded. \r
858         INITCOMMONCONTROLSEX icex;\r
859         icex.dwSize = sizeof(INITCOMMONCONTROLSEX);\r
860         icex.dwICC  = ICC_BAR_CLASSES | ICC_WIN95_CLASSES;\r
861         InitCommonControlsEx(&icex);\r
862 \r
863         hwndTB = CreateWindowEx(0, \r
864                                                         TOOLBARCLASSNAME, \r
865                                                         (LPCTSTR)NULL,\r
866                                                         WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS, \r
867                                                         0, 0, 0, 0, \r
868                                                         *this,\r
869                                                         (HMENU)IDC_TORTOISEIDIFF, \r
870                                                         hResource, \r
871                                                         NULL);\r
872         if (hwndTB == INVALID_HANDLE_VALUE)\r
873                 return false;\r
874 \r
875         SendMessage(hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);\r
876 \r
877         TBBUTTON tbb[12];\r
878         // create an imagelist containing the icons for the toolbar\r
879         hToolbarImgList = ImageList_Create(24, 24, ILC_COLOR32 | ILC_MASK, 12, 4);\r
880         if (hToolbarImgList == NULL)\r
881                 return false;\r
882         int index = 0;\r
883         HICON hIcon = LoadIcon(hResource, MAKEINTRESOURCE(IDI_OVERLAP));\r
884         tbb[index].iBitmap = ImageList_AddIcon(hToolbarImgList, hIcon); \r
885         tbb[index].idCommand = ID_VIEW_OVERLAPIMAGES; \r
886         tbb[index].fsState = TBSTATE_ENABLED; \r
887         tbb[index].fsStyle = BTNS_BUTTON; \r
888         tbb[index].dwData = 0; \r
889         tbb[index++].iString = 0; \r
890 \r
891         hIcon = LoadIcon(hResource, MAKEINTRESOURCE(IDI_BLEND));\r
892         tbb[index].iBitmap = ImageList_AddIcon(hToolbarImgList, hIcon); \r
893         tbb[index].idCommand = ID_VIEW_BLENDALPHA; \r
894         tbb[index].fsState = 0; \r
895         tbb[index].fsStyle = BTNS_BUTTON; \r
896         tbb[index].dwData = 0; \r
897         tbb[index++].iString = 0; \r
898 \r
899         hIcon = LoadIcon(hResource, MAKEINTRESOURCE(IDI_LINK));\r
900         tbb[index].iBitmap = ImageList_AddIcon(hToolbarImgList, hIcon); \r
901         tbb[index].idCommand = ID_VIEW_LINKIMAGESTOGETHER; \r
902         tbb[index].fsState = TBSTATE_ENABLED | TBSTATE_CHECKED; \r
903         tbb[index].fsStyle = BTNS_BUTTON; \r
904         tbb[index].dwData = 0; \r
905         tbb[index++].iString = 0; \r
906 \r
907         hIcon = LoadIcon(hResource, MAKEINTRESOURCE(IDI_FITTOGETHER));\r
908         tbb[index].iBitmap = ImageList_AddIcon(hToolbarImgList, hIcon); \r
909         tbb[index].idCommand = ID_VIEW_FITTOGETHER; \r
910         tbb[index].fsState = TBSTATE_ENABLED; \r
911         tbb[index].fsStyle = BTNS_BUTTON; \r
912         tbb[index].dwData = 0; \r
913         tbb[index++].iString = 0; \r
914 \r
915         tbb[index].iBitmap = 0; \r
916         tbb[index].idCommand = 0; \r
917         tbb[index].fsState = TBSTATE_ENABLED; \r
918         tbb[index].fsStyle = BTNS_SEP; \r
919         tbb[index].dwData = 0; \r
920         tbb[index++].iString = 0; \r
921 \r
922         hIcon = LoadIcon(hResource, MAKEINTRESOURCE(IDI_VERTICAL));\r
923         tbb[index].iBitmap = ImageList_AddIcon(hToolbarImgList, hIcon); \r
924         tbb[index].idCommand = ID_VIEW_ARRANGEVERTICAL; \r
925         tbb[index].fsState = TBSTATE_ENABLED; \r
926         tbb[index].fsStyle = BTNS_BUTTON; \r
927         tbb[index].dwData = 0; \r
928         tbb[index++].iString = 0; \r
929 \r
930         hIcon = LoadIcon(hResource, MAKEINTRESOURCE(IDI_FITINWINDOW));\r
931         tbb[index].iBitmap = ImageList_AddIcon(hToolbarImgList, hIcon); \r
932         tbb[index].idCommand = ID_VIEW_FITIMAGESINWINDOW; \r
933         tbb[index].fsState = TBSTATE_ENABLED; \r
934         tbb[index].fsStyle = BTNS_BUTTON; \r
935         tbb[index].dwData = 0; \r
936         tbb[index++].iString = 0; \r
937 \r
938         hIcon = LoadIcon(hResource, MAKEINTRESOURCE(IDI_ORIGSIZE));\r
939         tbb[index].iBitmap = ImageList_AddIcon(hToolbarImgList, hIcon); \r
940         tbb[index].idCommand = ID_VIEW_ORININALSIZE; \r
941         tbb[index].fsState = TBSTATE_ENABLED; \r
942         tbb[index].fsStyle = BTNS_BUTTON; \r
943         tbb[index].dwData = 0; \r
944         tbb[index++].iString = 0; \r
945 \r
946         hIcon = LoadIcon(hResource, MAKEINTRESOURCE(IDI_ZOOMIN));\r
947         tbb[index].iBitmap = ImageList_AddIcon(hToolbarImgList, hIcon); \r
948         tbb[index].idCommand = ID_VIEW_ZOOMIN; \r
949         tbb[index].fsState = TBSTATE_ENABLED; \r
950         tbb[index].fsStyle = BTNS_BUTTON; \r
951         tbb[index].dwData = 0; \r
952         tbb[index++].iString = 0; \r
953 \r
954         hIcon = LoadIcon(hResource, MAKEINTRESOURCE(IDI_ZOOMOUT));\r
955         tbb[index].iBitmap = ImageList_AddIcon(hToolbarImgList, hIcon); \r
956         tbb[index].idCommand = ID_VIEW_ZOOMOUT; \r
957         tbb[index].fsState = TBSTATE_ENABLED; \r
958         tbb[index].fsStyle = BTNS_BUTTON; \r
959         tbb[index].dwData = 0; \r
960         tbb[index++].iString = 0; \r
961 \r
962         tbb[index].iBitmap = 0; \r
963         tbb[index].idCommand = 0; \r
964         tbb[index].fsState = TBSTATE_ENABLED; \r
965         tbb[index].fsStyle = BTNS_SEP; \r
966         tbb[index].dwData = 0; \r
967         tbb[index++].iString = 0; \r
968 \r
969         hIcon = LoadIcon(hResource, MAKEINTRESOURCE(IDI_IMGINFO));\r
970         tbb[index].iBitmap = ImageList_AddIcon(hToolbarImgList, hIcon); \r
971         tbb[index].idCommand = ID_VIEW_IMAGEINFO; \r
972         tbb[index].fsState = TBSTATE_ENABLED; \r
973         tbb[index].fsStyle = BTNS_BUTTON; \r
974         tbb[index].dwData = 0; \r
975         tbb[index++].iString = 0; \r
976 \r
977         SendMessage(hwndTB, TB_SETIMAGELIST, 0, (LPARAM)hToolbarImgList);\r
978         SendMessage(hwndTB, TB_ADDBUTTONS, (WPARAM)index, (LPARAM) (LPTBBUTTON) &tbb); \r
979         SendMessage(hwndTB, TB_AUTOSIZE, 0, 0); \r
980         ShowWindow(hwndTB, SW_SHOW); \r
981         return true; \r
982 \r
983 }\r