OSDN Git Service

* WinIMergeLib: Add GetActivePane(), SetActivePane(),
authorsdottaka <sdottaka@sourceforge.net>
Fri, 12 Sep 2014 10:19:47 +0000 (19:19 +0900)
committersdottaka <sdottaka@sourceforge.net>
Fri, 12 Sep 2014 10:19:47 +0000 (19:19 +0900)
                FirstConflict(),
                LastConflict(), NextConflict(), PrevConflict(),
                AddEventListener()
* WinIMergeLib: Draw focus rectangle
* WinIMerge: Add context menu
* WinIMerge: Add "Next Conflict", "Previous conflict" menu item

src/CImgMergeWindow.hpp
src/CImgWindow.hpp
src/WinIMerge.cpp
src/WinIMerge.rc
src/WinIMergeLib.h
src/resource.h

index ad3e800..ba91f50 100644 (file)
@@ -21,6 +21,7 @@
 #include <string>\r
 #include <algorithm>\r
 #include <cstdio>\r
+#include <array>\r
 #include "FreeImagePlus.h"\r
 #include "CImgWindow.hpp"\r
 #include "WinIMergeLib.h"\r
@@ -109,8 +110,26 @@ template <class T> struct Array2D
        T* m_data;\r
 };\r
 \r
+struct DiffInfo\r
+{\r
+       enum OP_TYPE\r
+       {\r
+               OP_NONE = 0, OP_1STONLY, OP_2NDONLY, OP_3RDONLY, OP_DIFF, OP_TRIVIAL\r
+       };\r
+       DiffInfo(int op, int x, int y) : op(op), pt(x, y) {}\r
+       int op;\r
+       Point<int> pt;\r
+};\r
+\r
 class CImgMergeWindow : public IImgMergeWindow\r
 {\r
+       struct EventListenerInfo \r
+       {\r
+               EventListenerInfo(EventListenerFunc func, void *userdata) : func(func), userdata(userdata) {}\r
+               EventListenerFunc func;\r
+               void *userdata;\r
+       };\r
+\r
 public:\r
        CImgMergeWindow() : \r
                  m_nImages(0)\r
@@ -125,7 +144,9 @@ public:
                , m_selDiffColor(RGB(0xff, 0x40, 0x40))\r
                , m_diffColor(RGB(0xff, 0xff, 0x40))\r
                , m_currentDiffIndex(-1)\r
-       {}\r
+       {\r
+               memset(m_ChildWndProc, 0, sizeof(m_ChildWndProc));\r
+       }\r
 \r
        ~CImgMergeWindow()\r
        {\r
@@ -147,12 +168,30 @@ public:
                return !!bSucceeded;\r
        }\r
 \r
+       void AddEventListener(EventListenerFunc func, void *userdata)\r
+       {\r
+               m_listener.push_back(EventListenerInfo(func, userdata));\r
+       }\r
+\r
        bool SetWindowRect(const RECT& rc)\r
        {\r
                MoveWindow(m_hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);\r
                return true;\r
        }\r
 \r
+       int GetActivePane() const\r
+       {\r
+               for (int i = 0; i < m_nImages; ++i)\r
+                       if (m_imgWindow[i].IsFocused())\r
+                               return i;\r
+               return -1;\r
+       }\r
+\r
+       void SetActivePane(int pane)\r
+       {\r
+               m_imgWindow[pane].SetFocus();\r
+       }\r
+\r
        bool GetHorizontalSplit() const\r
        {\r
                return m_bHorizontalSplit;\r
@@ -354,6 +393,46 @@ public:
                return true;\r
        }\r
 \r
+       bool FirstConflict()\r
+       {\r
+               for (int i = 0; m_diffInfos.size(); ++i)\r
+                       if (m_diffInfos[i].op == DiffInfo::OP_DIFF)\r
+                               m_currentDiffIndex = i;\r
+               RefreshImages();\r
+               ScrollToDiff(m_currentDiffIndex);\r
+               return true;\r
+       }\r
+\r
+       bool LastConflict()\r
+       {\r
+               for (int i = m_diffInfos.size() - 1; i >= 0; --i)\r
+                       if (m_diffInfos[i].op == DiffInfo::OP_DIFF)\r
+                               m_currentDiffIndex = i;\r
+               RefreshImages();\r
+               ScrollToDiff(m_currentDiffIndex);\r
+               return true;\r
+       }\r
+\r
+       bool NextConflict()\r
+       {\r
+               for (int i = m_currentDiffIndex + 1; i < m_diffInfos.size(); ++i)\r
+                       if (m_diffInfos[i].op == DiffInfo::OP_DIFF)\r
+                               m_currentDiffIndex = i;\r
+               RefreshImages();\r
+               ScrollToDiff(m_currentDiffIndex);\r
+               return true;\r
+       }\r
+\r
+       bool PrevConflict()\r
+       {\r
+               for (int i = m_currentDiffIndex - 1; i >= 0; --i)\r
+                       if (m_diffInfos[i].op == DiffInfo::OP_DIFF)\r
+                               m_currentDiffIndex = i;\r
+               RefreshImages();\r
+               ScrollToDiff(m_currentDiffIndex);\r
+               return true;\r
+       }\r
+\r
        void CompareImages()\r
        {\r
                if (m_nImages <= 1)\r
@@ -370,8 +449,9 @@ public:
                        {\r
                                CompareImages2(0, 1, m_diff01);\r
                                CompareImages2(2, 1, m_diff21);\r
+                               CompareImages2(0, 2, m_diff02);\r
                                Make3WayDiff(m_diff01, m_diff21, m_diff);\r
-                               m_diffCount = MarkDiffIndex(m_diff);\r
+                               m_diffCount = MarkDiffIndex3way(m_diff01, m_diff21, m_diff02, m_diff);\r
                        }\r
                }\r
                RefreshImages();\r
@@ -379,10 +459,10 @@ public:
 \r
        void ScrollToDiff(int diffIndex)\r
        {\r
-               if (diffIndex >= 0 && diffIndex < m_diffPositions.size())\r
+               if (diffIndex >= 0 && diffIndex < m_diffInfos.size())\r
                {\r
                        for (int i = 0; i < m_nImages; ++i)\r
-                               m_imgWindow[i].ScrollTo(m_diffPositions[diffIndex].x * m_diffBlockSize, m_diffPositions[diffIndex].y * m_diffBlockSize);\r
+                               m_imgWindow[i].ScrollTo(m_diffInfos[diffIndex].pt.x * m_diffBlockSize, m_diffInfos[diffIndex].pt.y * m_diffBlockSize);\r
                }\r
        }\r
 \r
@@ -415,18 +495,8 @@ public:
                }\r
                if (m_showDifferences)\r
                {\r
-                       if (m_nImages == 2)\r
-                       {\r
-                               MarkDiff(0, m_diff);\r
-                               MarkDiff(1, m_diff);\r
-                       }\r
-                       else if (m_nImages == 3)\r
-                       {\r
-                               MarkDiff(0, m_diff);\r
-                               MarkDiff(1, m_diff);\r
-                               MarkDiff(1, m_diff);\r
-                               MarkDiff(2, m_diff);\r
-                       }\r
+                       for (int i = 0; i < m_nImages; ++i)\r
+                               MarkDiff(i, m_diff);\r
                }\r
                for (int i = 0; i < m_nImages; ++i)\r
                        m_imgWindow[i].Invalidate();\r
@@ -447,11 +517,7 @@ public:
                for (int i = 0; i < nImages; ++i)\r
                {\r
                        m_imgWindow[i].Create(m_hInstance, m_hWnd);\r
-                       for (int j = 0; j < nImages; ++j)\r
-                       {\r
-                               if (i != j)\r
-                                       m_imgWindow[i].AddSibling(&m_imgWindow[j]);\r
-                       }\r
+                       m_ChildWndProc[i] = (WNDPROC)SetWindowLongPtr(m_imgWindow[i].GetHWND(), GWLP_WNDPROC, (LONG_PTR)&ChildWndProc);\r
                }\r
                CompareImages();\r
                std::vector<RECT> rects = CalcChildImgWindowRect(m_hWnd, nImages, m_bHorizontalSplit);\r
@@ -655,8 +721,10 @@ private:
                        m_diff01.resize(nBlocksX, nBlocksY);\r
                        m_diff21.clear();\r
                        m_diff21.resize(nBlocksX, nBlocksY);\r
+                       m_diff02.clear();\r
+                       m_diff02.resize(nBlocksX, nBlocksY);\r
                }\r
-               m_diffPositions.clear();\r
+               m_diffInfos.clear();\r
        }\r
 \r
        void InitializeDiffImages()\r
@@ -755,13 +823,13 @@ private:
        int MarkDiffIndex(Array2D<unsigned>& diff)\r
        {\r
                int diffCount = 0;\r
-               for (unsigned bx = 0; bx < diff.width(); ++bx)\r
+               for (unsigned by = 0; by < diff.height(); ++by)\r
                {\r
-                       for (unsigned by = 0; by < diff.height(); ++by)\r
+                       for (unsigned bx = 0; bx < diff.width(); ++bx)\r
                        {\r
                                if (diff(bx, by) == -1)\r
                                {\r
-                                       m_diffPositions.push_back(Point<int>(bx, by));\r
+                                       m_diffInfos.push_back(DiffInfo(DiffInfo::OP_DIFF, bx, by));\r
                                        ++diffCount;\r
                                        FloodFill8Directions(diff, bx, by, diffCount);\r
                                }\r
@@ -770,6 +838,45 @@ private:
                return diffCount;\r
        }\r
 \r
+       int MarkDiffIndex3way(Array2D<unsigned>& diff01, Array2D<unsigned>& diff21, Array2D<unsigned>& diff02, Array2D<unsigned>& diff3)\r
+       {\r
+               int diffCount = MarkDiffIndex(diff3);\r
+               std::vector<std::array<int, 4>> counter(m_diffInfos.size());\r
+               for (unsigned by = 0; by < diff3.height(); ++by)\r
+               {\r
+                       for (unsigned bx = 0; bx < diff3.width(); ++bx)\r
+                       {\r
+                               int diffIndex = diff3(bx, by);\r
+                               if (diffIndex == 0)\r
+                                       continue;\r
+                               --diffIndex;\r
+                               if (diff21(bx, by) == 0)\r
+                                       ++counter[diffIndex][0];\r
+                               else if (diff02(bx, by) == 0)\r
+                                       ++counter[diffIndex][1];\r
+                               else if (diff01(bx, by) == 0)\r
+                                       ++counter[diffIndex][2];\r
+                               else\r
+                                       ++counter[diffIndex][3];\r
+                       }\r
+               }\r
+               \r
+               for (int i = 0; i < m_diffInfos.size(); ++i)\r
+               {\r
+                       int op;\r
+                       if (counter[i][0] != 0 && counter[i][1] == 0 && counter[i][2] == 0 && counter[i][3] == 0)\r
+                               op = DiffInfo::OP_1STONLY;\r
+                       else if (counter[i][0] == 0 && counter[i][1] != 0 && counter[i][2] == 0 && counter[i][3] == 0)\r
+                               op = DiffInfo::OP_2NDONLY;\r
+                       else if (counter[i][0] == 0 && counter[i][1] == 0 && counter[i][2] != 0 && counter[i][3] == 0)\r
+                               op = DiffInfo::OP_3RDONLY;\r
+                       else\r
+                               op = DiffInfo::OP_DIFF;\r
+                       m_diffInfos[i].op = op;\r
+               }\r
+               return diffCount;\r
+       }\r
+\r
        void Make3WayDiff(const Array2D<unsigned>& diff01, const Array2D<unsigned>& diff21, Array2D<unsigned>& diff3)\r
        {\r
                diff3 = diff01;\r
@@ -794,7 +901,11 @@ private:
                        for (unsigned bx = 0; bx < diff.width(); ++bx)\r
                        {\r
                                unsigned diffIndex = diff(bx, by);\r
-                               if (diffIndex != 0)\r
+                               if (diffIndex != 0 && (\r
+                                       (pane == 0 && m_diffInfos[diffIndex - 1].op != DiffInfo::OP_3RDONLY) ||\r
+                                       (pane == 1) ||\r
+                                       (pane == 2 && m_diffInfos[diffIndex - 1].op != DiffInfo::OP_1STONLY)\r
+                                       ))\r
                                {\r
                                        COLORREF color = (diffIndex - 1 == m_currentDiffIndex) ? m_selDiffColor : m_diffColor;\r
                                        unsigned bsy = (h - by * m_diffBlockSize < m_diffBlockSize) ? (h - by * m_diffBlockSize) : m_diffBlockSize;\r
@@ -847,7 +958,6 @@ private:
                                scanline_dst[x * 4 + 0] ^= scanline_src[x * 4 + 0];\r
                                scanline_dst[x * 4 + 1] ^= scanline_src[x * 4 + 1];\r
                                scanline_dst[x * 4 + 2] ^= scanline_src[x * 4 + 2];\r
-                               //scanline_dst[x * 4 + 3] ^= scanline_src[x * 4 + 3];\r
                        }\r
                }       \r
        }\r
@@ -968,6 +1078,14 @@ private:
 \r
        void OnDestroy()\r
        {\r
+               for (int i = 0; i < m_nImages; ++i)\r
+               {\r
+                       if (m_ChildWndProc[i])\r
+                       {\r
+                               SetWindowLongPtr(m_imgWindow[i].GetHWND(), GWLP_WNDPROC, (LONG_PTR)m_ChildWndProc[i]);\r
+                               m_ChildWndProc[i] = NULL;\r
+                       }\r
+               }\r
        }\r
 \r
        LRESULT OnWndMsg(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)\r
@@ -977,6 +1095,9 @@ private:
                case WM_CREATE:\r
                        OnCreate(hwnd, (LPCREATESTRUCT)lParam);\r
                        break;\r
+               case WM_COMMAND:\r
+                       PostMessage(GetParent(m_hWnd), iMsg, wParam, lParam);\r
+                       break;\r
                case WM_SIZE:\r
                        OnSize((UINT)wParam, LOWORD(lParam), HIWORD(lParam));\r
                        break;\r
@@ -1010,6 +1131,77 @@ private:
                return lResult;\r
        }\r
 \r
+       static LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)\r
+       {\r
+               Event evt;\r
+               int i;\r
+               CImgMergeWindow *pImgWnd = (CImgMergeWindow *)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA);\r
+               for (i = 0; i < pImgWnd->m_nImages; ++i)\r
+                       if (pImgWnd->m_imgWindow[i].GetHWND() == hwnd)\r
+                               break;\r
+               evt.pane = i;\r
+               evt.flags = (unsigned)wParam; \r
+               evt.x = (int)(short)LOWORD(lParam);\r
+               evt.y = (int)(short)HIWORD(lParam);\r
+               switch(iMsg)\r
+               {\r
+               case WM_LBUTTONDOWN:\r
+                       evt.eventType = LBUTTONDOWN; goto NEXT;\r
+               case WM_LBUTTONUP:\r
+                       evt.eventType = LBUTTONUP; goto NEXT;\r
+               case WM_LBUTTONDBLCLK:\r
+                       evt.eventType = LBUTTONDBLCLK; goto NEXT;\r
+               case WM_RBUTTONDOWN:\r
+                       evt.eventType = RBUTTONDOWN; goto NEXT;\r
+               case WM_RBUTTONUP:\r
+                       evt.eventType = RBUTTONUP; goto NEXT;\r
+               case WM_RBUTTONDBLCLK:\r
+                       evt.eventType = RBUTTONDBLCLK; goto NEXT;\r
+               case WM_MOUSEMOVE:\r
+                       evt.eventType = MOUSEMOVE; goto NEXT;\r
+               case WM_MOUSEWHEEL:\r
+                       evt.flags = GET_KEYSTATE_WPARAM(wParam);\r
+                       evt.eventType = MOUSEWHEEL;\r
+                       evt.delta = GET_WHEEL_DELTA_WPARAM(wParam);\r
+                       goto NEXT;\r
+               case WM_CONTEXTMENU:\r
+                       evt.eventType = CONTEXTMENU; goto NEXT;\r
+               case WM_SIZE:\r
+                       evt.eventType = SIZE; evt.width = LOWORD(lParam); evt.height = HIWORD(wParam); goto NEXT;\r
+               case WM_HSCROLL:\r
+                       evt.eventType = HSCROLL;goto NEXT;\r
+               case WM_VSCROLL:\r
+                       evt.eventType = VSCROLL; goto NEXT;\r
+               case WM_SETFOCUS:\r
+                       evt.eventType = SETFOCUS; goto NEXT;\r
+               case WM_KILLFOCUS:\r
+                       evt.eventType = KILLFOCUS; goto NEXT;\r
+               NEXT:\r
+               {\r
+                       std::vector<EventListenerInfo>::iterator it;\r
+                       for (it = pImgWnd->m_listener.begin(); it != pImgWnd->m_listener.end(); ++it)\r
+                       {\r
+                               evt.userdata = (*it).userdata;\r
+                               (*it).func(evt);\r
+                       }\r
+                       break;\r
+               }\r
+               }\r
+               switch (iMsg)\r
+               {\r
+               case WM_HSCROLL:\r
+               case WM_VSCROLL:\r
+               case WM_MOUSEWHEEL:\r
+                       for (int j = 0; j < pImgWnd->m_nImages; ++j)\r
+                       {\r
+                               if (j != i)\r
+                                       (pImgWnd->m_ChildWndProc[j])(pImgWnd->m_imgWindow[j].GetHWND(), iMsg, wParam, lParam);\r
+                       }\r
+                       break;\r
+               }\r
+               return (pImgWnd->m_ChildWndProc[i])(hwnd, iMsg, wParam, lParam);\r
+       }\r
+\r
        int m_nImages;\r
        HWND m_hWnd;\r
        HINSTANCE m_hInstance;\r
@@ -1018,6 +1210,8 @@ private:
        fipImage m_imgOrig32[3];\r
        fipWinImage m_imgDiff[3];\r
        CImgWindow m_imgWindow[3];\r
+       WNDPROC m_ChildWndProc[3];\r
+       std::vector<EventListenerInfo> m_listener;\r
        std::wstring m_filename[3];\r
        int m_nDraggingSplitter;\r
        bool m_bHorizontalSplit;\r
@@ -1032,6 +1226,6 @@ private:
        int m_currentPage[3];\r
        int m_currentDiffIndex;\r
        int m_diffCount;\r
-       Array2D<unsigned> m_diff, m_diff01, m_diff21;\r
-       std::vector<Point<int> > m_diffPositions;\r
+       Array2D<unsigned> m_diff, m_diff01, m_diff21, m_diff02;\r
+       std::vector<DiffInfo> m_diffInfos;\r
 };\r
index 9bb4c41..dea5a94 100644 (file)
@@ -29,7 +29,6 @@ public:
                , m_nVScrollPos(0)\r
                , m_nHScrollPos(0)\r
                , m_zoom(1.0)\r
-               , m_inEvent(false)\r
                , m_useBackColor(true)\r
        {\r
                memset(&m_backColor, 0xff, sizeof(m_backColor));\r
@@ -58,7 +57,6 @@ public:
                        DestroyWindow(m_hWnd);\r
                m_fip = NULL;\r
                m_hWnd = NULL;\r
-               m_siblings.clear();\r
                return true;\r
        }\r
 \r
@@ -80,6 +78,16 @@ public:
                MoveWindow(m_hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);\r
        }\r
 \r
+       void SetFocus()\r
+       {\r
+               ::SetFocus(m_hWnd);\r
+       }\r
+\r
+       bool IsFocused() const\r
+       {\r
+               return m_hWnd == GetFocus();\r
+       }\r
+\r
        void ScrollTo(int x, int y)\r
        {\r
                SCROLLINFO sih = {0}, siv = {0};\r
@@ -116,7 +124,8 @@ public:
                                m_nVScrollPos = siv.nMax - siv.nPage;\r
                }\r
 \r
-               ScrollWindow(m_hWnd, sih.nPos - m_nHScrollPos, siv.nPos - m_nVScrollPos, NULL, NULL);\r
+               RECT rcClip = {rc.left + 1, rc.top + 1, rc.right - 1, rc.bottom - 1};\r
+               ScrollWindow(m_hWnd, sih.nPos - m_nHScrollPos, siv.nPos - m_nVScrollPos, NULL, &rcClip);\r
                CalcScrollBarRange();\r
                InvalidateRect(m_hWnd, NULL, TRUE);\r
        }\r
@@ -172,11 +181,6 @@ public:
                CalcScrollBarRange();\r
        }\r
 \r
-       void AddSibling(CImgWindow *pImgWindow)\r
-       {\r
-               m_siblings.push_back(pImgWindow);\r
-       }\r
-\r
 private:\r
 \r
        ATOM MyRegisterClass(HINSTANCE hInstance)\r
@@ -223,6 +227,20 @@ private:
                                rcImg.bottom = static_cast<int>(m_fip->getHeight() * m_zoom - m_nVScrollPos);\r
                        }\r
                        m_fip->drawEx(hdc, rcImg, false, m_useBackColor ? &m_backColor : NULL);\r
+                       if (GetFocus() == m_hWnd)\r
+                       {\r
+                               DrawFocusRect(hdc, &rc);\r
+                       }\r
+                       else\r
+                       {\r
+                               HPEN hPen = (HPEN)GetStockObject(WHITE_PEN);\r
+                               HBRUSH hBrush = (HBRUSH)GetStockObject(NULL_BRUSH);\r
+                               HPEN hOldPen = (HPEN)SelectObject(hdc, hPen);\r
+                               HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);\r
+                               Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);\r
+                               SelectObject(hdc, hOldPen);\r
+                               SelectObject(hdc, hOldBrush);\r
+                       }\r
                }\r
                EndPaint(m_hWnd, &ps);\r
        }\r
@@ -234,9 +252,6 @@ private:
 \r
        void OnHScroll(UINT nSBCode, UINT nPos)\r
        {\r
-               if (m_inEvent)\r
-                       return;\r
-\r
                SCROLLINFO si = {0};\r
                si.cbSize = sizeof SCROLLINFO;\r
                si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE | SIF_TRACKPOS;\r
@@ -263,21 +278,15 @@ private:
                        m_nHScrollPos = 0;\r
                if (m_nHScrollPos > si.nMax - static_cast<int>(si.nPage))\r
                        m_nHScrollPos = si.nMax - si.nPage;\r
-               ScrollWindow(m_hWnd, si.nPos - m_nHScrollPos, 0, NULL, NULL);\r
+               RECT rc;\r
+               GetClientRect(m_hWnd, &rc);\r
+               RECT rcClip = {rc.left + 1, rc.top + 1, rc.right - 1, rc.bottom - 1};\r
+               ScrollWindow(m_hWnd, si.nPos - m_nHScrollPos, 0, NULL, &rcClip);\r
                CalcScrollBarRange();\r
-\r
-               m_inEvent = true;\r
-               std::vector<CImgWindow *>::iterator it;\r
-               for (it = m_siblings.begin(); it != m_siblings.end(); ++it)\r
-                       (*it)->OnHScroll(nSBCode, nPos);\r
-               m_inEvent = false;\r
        }\r
 \r
        void OnVScroll(UINT nSBCode, UINT nPos)\r
        {\r
-               if (m_inEvent)\r
-                       return;\r
-\r
                SCROLLINFO si = {0};\r
                si.cbSize = sizeof SCROLLINFO;\r
                si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE | SIF_TRACKPOS;\r
@@ -304,43 +313,64 @@ private:
                        m_nVScrollPos = 0;\r
                if (m_nVScrollPos > si.nMax - static_cast<int>(si.nPage))\r
                        m_nVScrollPos = si.nMax - si.nPage;\r
-               ScrollWindow(m_hWnd, 0, si.nPos - m_nVScrollPos, NULL, NULL);\r
+               RECT rc;\r
+               GetClientRect(m_hWnd, &rc);\r
+               RECT rcClip = {rc.left + 1, rc.top + 1, rc.right - 1, rc.bottom - 1};\r
+               ScrollWindow(m_hWnd, 0, si.nPos - m_nVScrollPos, NULL, &rcClip);\r
                CalcScrollBarRange();\r
-\r
-               m_inEvent = true;\r
-               std::vector<CImgWindow *>::iterator it;\r
-               for (it = m_siblings.begin(); it != m_siblings.end(); ++it)\r
-                       (*it)->OnVScroll(nSBCode, nPos);\r
-               m_inEvent = false;\r
        }\r
 \r
        void OnLButtonDown(UINT nFlags, int x, int y)\r
        {\r
+               SetFocus();\r
        }\r
 \r
-       void OnMouseWheel(UINT nFlags, short zDelta)\r
+       void OnRButtonDown(UINT nFlags, int x, int y)\r
        {\r
-               if (m_inEvent)\r
-                       return;\r
+               SetFocus();\r
+       }\r
 \r
-               const bool ctrlDown = (GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0;\r
-               if (!ctrlDown)\r
+       void OnMouseWheel(UINT nFlags, short zDelta)\r
+       {\r
+               if (!(nFlags & MK_CONTROL))\r
                { \r
                        RECT rc;\r
                        GetClientRect(m_hWnd, &rc);\r
-                       if (rc.bottom - rc.top < m_fip->getHeight() * m_zoom)\r
+                       if (!(nFlags & MK_SHIFT))\r
                        {\r
-                               SCROLLINFO si = {0};\r
-                               si.cbSize = sizeof SCROLLINFO;\r
-                               si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE | SIF_TRACKPOS;\r
-                               GetScrollInfo(m_hWnd, SB_VERT, &si);\r
-                               m_nVScrollPos += - zDelta / (WHEEL_DELTA / 16);\r
-                               if (m_nVScrollPos < 0)\r
-                                       m_nVScrollPos = 0;\r
-                               if (m_nVScrollPos > si.nMax - static_cast<int>(si.nPage))\r
-                                       m_nVScrollPos = si.nMax - si.nPage;\r
-                               ScrollWindow(m_hWnd, 0, si.nPos - m_nVScrollPos, NULL, NULL);\r
-                               CalcScrollBarRange();\r
+                               if (rc.bottom - rc.top < m_fip->getHeight() * m_zoom)\r
+                               {\r
+                                       SCROLLINFO si = {0};\r
+                                       si.cbSize = sizeof SCROLLINFO;\r
+                                       si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE | SIF_TRACKPOS;\r
+                                       GetScrollInfo(m_hWnd, SB_VERT, &si);\r
+                                       m_nVScrollPos += - zDelta / (WHEEL_DELTA / 16);\r
+                                       if (m_nVScrollPos < 0)\r
+                                               m_nVScrollPos = 0;\r
+                                       if (m_nVScrollPos > si.nMax - static_cast<int>(si.nPage))\r
+                                               m_nVScrollPos = si.nMax - si.nPage;\r
+                                       RECT rcClip = {rc.left + 1, rc.top + 1, rc.right - 1, rc.bottom - 1};\r
+                                       ScrollWindow(m_hWnd, 0, si.nPos - m_nVScrollPos, NULL, &rcClip);\r
+                                       CalcScrollBarRange();\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               if (rc.right - rc.left < m_fip->getWidth() * m_zoom)\r
+                               {\r
+                                       SCROLLINFO si = {0};\r
+                                       si.cbSize = sizeof SCROLLINFO;\r
+                                       si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE | SIF_TRACKPOS;\r
+                                       GetScrollInfo(m_hWnd, SB_HORZ, &si);\r
+                                       m_nHScrollPos += - zDelta / (WHEEL_DELTA / 16);\r
+                                       if (m_nHScrollPos < 0)\r
+                                               m_nHScrollPos = 0;\r
+                                       if (m_nHScrollPos > si.nMax - static_cast<int>(si.nPage))\r
+                                               m_nHScrollPos = si.nMax - si.nPage;\r
+                                       RECT rcClip = {rc.left + 1, rc.top + 1, rc.right - 1, rc.bottom - 1};\r
+                                       ScrollWindow(m_hWnd, si.nPos - m_nHScrollPos, 0, NULL, &rcClip);\r
+                                       CalcScrollBarRange();\r
+                               }\r
                        }\r
                }\r
                else\r
@@ -350,12 +380,16 @@ private:
                        else\r
                                SetZoom(m_zoom * 0.8);\r
                }\r
+       }\r
 \r
-               m_inEvent = true;\r
-               std::vector<CImgWindow *>::iterator it;\r
-               for (it = m_siblings.begin(); it != m_siblings.end(); ++it)\r
-                       (*it)->OnMouseWheel(nFlags, zDelta);\r
-               m_inEvent = false;\r
+       void OnSetFocus(HWND hwndOld)\r
+       {\r
+               InvalidateRect(m_hWnd, NULL, TRUE);\r
+       }\r
+\r
+       void OnKillFocus(HWND hwndNew)\r
+       {\r
+               InvalidateRect(m_hWnd, NULL, TRUE);\r
        }\r
 \r
        LRESULT OnWndMsg(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)\r
@@ -374,9 +408,21 @@ private:
                case WM_LBUTTONDOWN:\r
                        OnLButtonDown((UINT)(wParam), (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam));\r
                        break;\r
+               case WM_RBUTTONDOWN:\r
+                       OnRButtonDown((UINT)(wParam), (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam));\r
+                       break;\r
                case WM_MOUSEWHEEL:\r
                        OnMouseWheel(GET_KEYSTATE_WPARAM(wParam), GET_WHEEL_DELTA_WPARAM(wParam));\r
                        break;\r
+               case WM_SETFOCUS:\r
+                       OnSetFocus((HWND)wParam);\r
+                       break;\r
+               case WM_KILLFOCUS:\r
+                       OnKillFocus((HWND)wParam);\r
+                       break;\r
+               case WM_COMMAND:\r
+                       PostMessage(GetParent(m_hWnd), iMsg, wParam, lParam);\r
+                       break;\r
                case WM_SIZE:\r
                        OnSize((UINT)wParam, LOWORD(lParam), HIWORD(lParam));\r
                        break;\r
@@ -426,8 +472,6 @@ private:
        int m_nVScrollPos;\r
        int m_nHScrollPos;\r
        double m_zoom;\r
-       std::vector<CImgWindow *> m_siblings;\r
-       bool m_inEvent;\r
        bool m_useBackColor;\r
        RGBQUAD m_backColor;\r
 };
\ No newline at end of file
index 9b8996f..af99c86 100644 (file)
@@ -157,12 +157,23 @@ void UpdateMenuState(HWND hWnd)
        CheckMenuItem(hMenu, ID_VIEW_USEBACKCOLOR, m_pImgMergeWindow->GetUseBackColor() ? MF_CHECKED : MF_UNCHECKED);\r
 }\r
 \r
+void OnChildPaneEvent(const IImgMergeWindow::Event& evt)\r
+{\r
+       if (evt.eventType == IImgMergeWindow::CONTEXTMENU)\r
+       {\r
+               HMENU hPopup = LoadMenu(m_hInstance, MAKEINTRESOURCE(IDR_POPUPMENU));\r
+               HMENU hSubMenu = GetSubMenu(hPopup, 0);\r
+               TrackPopupMenu(hSubMenu, TPM_LEFTALIGN, evt.x, evt.y, 0, m_hWnd, NULL); \r
+       }\r
+}\r
+\r
 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
 {\r
        switch (message) \r
        {\r
        case WM_CREATE:\r
                m_pImgMergeWindow = WinIMerge_CreateWindow(hInstDLL, hWnd);\r
+               m_pImgMergeWindow->AddEventListener(OnChildPaneEvent, NULL);\r
                UpdateMenuState(hWnd);\r
                break;\r
        case WM_SIZE:\r
@@ -299,6 +310,12 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
                case ID_MERGE_LASTDIFFERENCE:\r
                        m_pImgMergeWindow->LastDiff();\r
                        break;\r
+               case ID_MERGE_NEXTCONFLICT:\r
+                       m_pImgMergeWindow->NextConflict();\r
+                       break;\r
+               case ID_MERGE_PREVIOUSCONFLICT:\r
+                       m_pImgMergeWindow->PrevConflict();\r
+                       break;\r
                case ID_HELP_ABOUT:\r
                        MessageBoxW(hWnd, \r
                                L"WinIMerge\n\n"\r
@@ -307,6 +324,18 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
                                L"See http://freeimage.sourceforge.net for details.\n"\r
                                L"FreeImage is used under the GNU GPL version.\n", L"WinIMerge", MB_OK | MB_ICONINFORMATION);\r
                        break;\r
+               case ID_POPUP_CURPANE_PREVIOUSPAGE:\r
+               {\r
+                       int nActivePane = m_pImgMergeWindow->GetActivePane();\r
+                       m_pImgMergeWindow->SetCurrentPage(nActivePane, m_pImgMergeWindow->GetCurrentPage(nActivePane) - 1);\r
+                       break;\r
+               }\r
+               case ID_POPUP_CURPANE_NEXTPAGE:\r
+               {\r
+                       int nActivePane = m_pImgMergeWindow->GetActivePane();\r
+                       m_pImgMergeWindow->SetCurrentPage(nActivePane, m_pImgMergeWindow->GetCurrentPage(nActivePane) + 1);\r
+                       break;\r
+               }\r
                default:\r
                        return DefWindowProc(hWnd, message, wParam, lParam);\r
                }\r
index 42e4498..560279e 100644 (file)
@@ -128,6 +128,8 @@ BEGIN
         MENUITEM "&Previous Difference\tAlt+Up", ID_MERGE_PREVIOUSDIFFERENCE\r
         MENUITEM "&First Difference\tAlt+Home", ID_MERGE_FIRSTDIFFERENCE\r
         MENUITEM "&Last Difference\tAlt+End",   ID_MERGE_LASTDIFFERENCE\r
+        MENUITEM "Next Conflict\tAlt+Shift+Down", ID_MERGE_NEXTCONFLICT\r
+        MENUITEM "Previous Conflict\tAlt+Shift+Up", ID_MERGE_PREVIOUSCONFLICT\r
     END\r
     POPUP "&Help"\r
     BEGIN\r
@@ -135,6 +137,15 @@ BEGIN
     END\r
 END\r
 \r
+IDR_POPUPMENU MENU\r
+BEGIN\r
+    POPUP "popup"\r
+    BEGIN\r
+        MENUITEM "Current Pane: &Previous Page", ID_POPUP_CURPANE_PREVIOUSPAGE\r
+        MENUITEM "Current Pane: &Next Page",    ID_POPUP_CURPANE_NEXTPAGE\r
+    END\r
+END\r
+\r
 \r
 /////////////////////////////////////////////////////////////////////////////\r
 //\r
@@ -143,10 +154,12 @@ END
 \r
 IDC_WINIMERGE ACCELERATORS\r
 BEGIN\r
-    VK_DOWN,        ID_MERGE_NEXTDIFFERENCE, VIRTKEY, ALT, NOINVERT\r
-    VK_UP,          ID_MERGE_PREVIOUSDIFFERENCE, VIRTKEY, ALT, NOINVERT\r
     VK_HOME,        ID_MERGE_FIRSTDIFFERENCE, VIRTKEY, ALT, NOINVERT\r
     VK_END,         ID_MERGE_LASTDIFFERENCE, VIRTKEY, ALT, NOINVERT\r
+    VK_DOWN,        ID_MERGE_NEXTDIFFERENCE, VIRTKEY, ALT, NOINVERT\r
+    VK_UP,          ID_MERGE_PREVIOUSDIFFERENCE, VIRTKEY, ALT, NOINVERT\r
+    VK_DOWN,        ID_MERGE_NEXTCONFLICT,  VIRTKEY, SHIFT, ALT, NOINVERT\r
+    VK_UP,          ID_MERGE_PREVIOUSCONFLICT, VIRTKEY, SHIFT, ALT, NOINVERT\r
 END\r
 \r
 #endif    // \89p\8cê (\95Ä\8d\91) resources\r
index c9b3626..9fc02e4 100644 (file)
@@ -22,9 +22,30 @@ struct IImgMergeWindow
        enum OVERLAY_MODE {\r
                OVERLAY_NONE = 0, OVERLAY_XOR, OVERLAY_ALPHABLEND\r
        };\r
+       enum EVENT_TYPE {\r
+               LBUTTONDOWN = 0, LBUTTONUP, LBUTTONDBLCLK, \r
+               RBUTTONDOWN,     RBUTTONUP, RBUTTONDBLCLK,\r
+               MOUSEMOVE, MOUSEWHEEL, CONTEXTMENU,\r
+               SIZE, HSCROLL, VSCROLL, SETFOCUS, KILLFOCUS\r
+       };\r
+       struct Event\r
+       {\r
+               void *userdata;\r
+               int pane;\r
+               EVENT_TYPE eventType;\r
+               int x;\r
+               int y;\r
+               unsigned flags;\r
+               int delta;\r
+               int width;\r
+               int height;\r
+       };\r
+       typedef void (*EventListenerFunc)(const Event& evt);\r
        virtual bool OpenImages(const wchar_t *filename1, const wchar_t *filename2) = 0;\r
        virtual bool OpenImages(const wchar_t *filename1, const wchar_t *filename2, const wchar_t *filename3) = 0;\r
        virtual bool SetWindowRect(const RECT& rc) = 0;\r
+       virtual int  GetActivePane() const = 0;\r
+       virtual void SetActivePane(int pane) = 0;\r
        virtual bool GetHorizontalSplit() const = 0;\r
        virtual void SetHorizontalSplit(bool horizontalSplit) = 0;\r
        virtual int  GetCurrentPage(int pane) const = 0;\r
@@ -53,7 +74,12 @@ struct IImgMergeWindow
        virtual bool LastDiff() = 0;\r
        virtual bool NextDiff() = 0;\r
        virtual bool PrevDiff() = 0;\r
+       virtual bool FirstConflict() = 0;\r
+       virtual bool LastConflict() = 0;\r
+       virtual bool NextConflict() = 0;\r
+       virtual bool PrevConflict() = 0;\r
        virtual HWND GetHWND() const = 0;\r
+       virtual void AddEventListener(EventListenerFunc func, void *userdata) = 0;\r
 };\r
 \r
 extern "C"\r
index aa84b5e..7289b3c 100644 (file)
@@ -9,6 +9,7 @@
 #define IDI_WINIMERGE                   108\r
 #define IDC_WINIMERGE                   110\r
 #define IDR_MAINFRAME                   128\r
+#define IDR_POPUPMENU                   130\r
 #define ID_VIEW_ZOOM_25                 32780\r
 #define ID_VIEW_ZOOM_50                 32781\r
 #define ID_VIEW_ZOOM_100                32782\r
 #define ID_MERGE_PREVIOUSDIFFERENCE     32797\r
 #define ID_MERGE_FIRSTDIFFERENCE        32798\r
 #define ID_MERGE_LASTDIFFERENCE         32799\r
-#define ID_EDIT_COPY                    32800\r
-#define ID_EDIT_CUT                     32801\r
-#define ID_EDIT_PASTE                   32802\r
-#define ID_EDIT_SELECTALL               32803\r
+#define ID_MERGE_NEXTCONFLICT           32800\r
+#define ID_MERGE_PREVIOUSCONFLICT       32801\r
+#define ID_EDIT_COPY                    32802\r
+#define ID_EDIT_CUT                     32803\r
+#define ID_EDIT_PASTE                   32804\r
+#define ID_EDIT_SELECTALL               32805\r
 #define ID_HELP_ABOUT                   32809\r
 #define ID_VIEW_DIFFBLOCKSIZE_1         32811\r
 #define ID_VIEW_DIFFBLOCKSIZE_2         32812\r
@@ -40,6 +43,8 @@
 #define ID_VIEW_PAGE_NEXTPAGE           32821\r
 #define ID_VIEW_PAGE_PREVPAGE           32822\r
 #define ID_VIEW_USEBACKCOLOR            32823\r
+#define ID_POPUP_CURPANE_NEXTPAGE       32824\r
+#define ID_POPUP_CURPANE_PREVIOUSPAGE   32825\r
 #define IDC_STATIC                      -1\r
 \r
 // Next default values for new objects\r
@@ -47,8 +52,8 @@
 #ifdef APSTUDIO_INVOKED\r
 #ifndef APSTUDIO_READONLY_SYMBOLS\r
 #define _APS_NO_MFC                     1\r
-#define _APS_NEXT_RESOURCE_VALUE        130\r
-#define _APS_NEXT_COMMAND_VALUE         32824\r
+#define _APS_NEXT_RESOURCE_VALUE        131\r
+#define _APS_NEXT_COMMAND_VALUE         32828\r
 #define _APS_NEXT_CONTROL_VALUE         1000\r
 #define _APS_NEXT_SYMED_VALUE           111\r
 #endif\r