3 Star 9 Fork 7

Gitee 极速下载/WinMerge

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
此仓库是为了提升国内下载速度的镜像仓库,每日同步一次。 原始仓库: https://github.com/winmerge/winmerge
克隆/下载
HexMergeFrm.cpp 12.28 KB
一键复制 编辑 原始数据 按行查看 历史
/////////////////////////////////////////////////////////////////////////////
// WinMerge: an interactive diff/merge utility
// Copyright (C) 1997-2000 Thingamahoochie Software
// Author: Dean Grimm
// SPDX-License-Identifier: GPL-2.0-or-later
/////////////////////////////////////////////////////////////////////////////
/**
* @file HexMergeFrm.cpp
*
* @brief Implementation file for CHexMergeFrame
*
*/
#include "stdafx.h"
#include "HexMergeFrm.h"
#include "Merge.h"
#include "HexMergeDoc.h"
#include "HexMergeView.h"
#include "OptionsDef.h"
#include "OptionsMgr.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define SWAPPARAMS_IF(c, a, b) (c ? a : b), (c ? b : a)
/////////////////////////////////////////////////////////////////////////////
// CHexMergeFrame
IMPLEMENT_DYNCREATE(CHexMergeFrame, CMergeFrameCommon)
BEGIN_MESSAGE_MAP(CHexMergeFrame, CMergeFrameCommon)
//{{AFX_MSG_MAP(CHexMergeFrame)
ON_WM_CREATE()
ON_WM_CLOSE()
ON_WM_SIZE()
ON_MESSAGE_VOID(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)
ON_MESSAGE(MSG_STORE_PANESIZES, OnStorePaneSizes)
// [View] menu
ON_COMMAND(ID_VIEW_SPLITVERTICALLY, OnViewSplitVertically)
ON_UPDATE_COMMAND_UI(ID_VIEW_SPLITVERTICALLY, OnUpdateViewSplitVertically)
//ON_UPDATE_COMMAND_UI(ID_VIEW_DETAIL_BAR, OnUpdateControlBarMenu)
//ON_COMMAND_EX(ID_VIEW_DETAIL_BAR, OnBarCheck)
//ON_UPDATE_COMMAND_UI(ID_VIEW_LOCATION_BAR, OnUpdateControlBarMenu)
//ON_COMMAND_EX(ID_VIEW_LOCATION_BAR, OnBarCheck)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/**
* @brief Statusbar pane indexes
*/
enum
{
PANE_LEFT_INFO = 0,
PANE_LEFT_RO,
PANE_LEFT_EOL,
PANE_RIGHT_INFO,
PANE_RIGHT_RO,
PANE_RIGHT_EOL,
};
/////////////////////////////////////////////////////////////////////////////
// CHexMergeFrame construction/destruction
CHexMergeFrame::CHexMergeFrame()
: CMergeFrameCommon(IDI_EQUALBINARY, IDI_BINARYDIFF)
, m_HScrollInfo{}, m_VScrollInfo{}
{
m_pMergeDoc = 0;
}
CHexMergeFrame::~CHexMergeFrame()
{
}
/**
* @brief Create a status bar to be associated with a heksedit control
*/
void CHexMergeFrame::CreateHexWndStatusBar(CStatusBar &wndStatusBar, CWnd *pwndPane)
{
const int lpx = CClientDC(this).GetDeviceCaps(LOGPIXELSX);
auto pointToPixel = [lpx](int point) { return MulDiv(point, lpx, 72); };
wndStatusBar.Create(pwndPane, WS_CHILD|WS_VISIBLE);
wndStatusBar.SetIndicators(0, 3);
wndStatusBar.SetPaneInfo(0, 0, SBPS_STRETCH | SBPS_CLICKABLE, 0);
wndStatusBar.SetPaneInfo(1, 0, SBPS_CLICKABLE, pointToPixel(60));
wndStatusBar.SetPaneInfo(2, 0, SBPS_CLICKABLE, pointToPixel(60));
wndStatusBar.SetParent(this);
wndStatusBar.SetWindowPos(&wndBottom, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}
/**
* @brief Create the splitter, the filename bar, the status bar, and the two views
*/
BOOL CHexMergeFrame::OnCreateClient( LPCREATESTRUCT /*lpcs*/,
CCreateContext* pContext)
{
m_pMergeDoc = dynamic_cast<CHexMergeDoc *>(pContext->m_pCurrentDoc);
bool bSplitVert = !GetOptionsMgr()->GetBool(OPT_SPLIT_HORIZONTALLY);
// create a splitter with 1 row, 2 columns
if (!m_wndSplitter.CreateStatic(this, SWAPPARAMS_IF(bSplitVert, 1, m_pMergeDoc->m_nBuffers), WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL) )
{
TRACE0("Failed to CreateStaticSplitter\n");
return FALSE;
}
int nPane;
for (nPane = 0; nPane < m_pMergeDoc->m_nBuffers; nPane++)
{
if (!m_wndSplitter.CreateView(SWAPPARAMS_IF(bSplitVert, 0, nPane),
RUNTIME_CLASS(CHexMergeView), CSize(-1, 200), pContext))
{
TRACE0("Failed to create first pane\n");
return FALSE;
}
}
m_wndSplitter.ResizablePanes(true);
m_wndSplitter.AutoResizePanes(GetOptionsMgr()->GetBool(OPT_RESIZE_PANES));
// Merge frame has a header bar at top
if (!m_wndFilePathBar.Create(this))
{
TRACE0("Failed to create dialog bar\n");
return FALSE; // fail to create
}
m_wndFilePathBar.SetPaneCount(m_pMergeDoc->m_nBuffers);
m_wndFilePathBar.SetOnSetFocusCallback([&](int pane) {
SetActivePane(pane);
});
m_wndFilePathBar.SetOnCaptionChangedCallback([&](int pane, const String& sText) {
m_pMergeDoc->SetDescription(pane ,sText);
m_pMergeDoc->UpdateHeaderPath(pane);
});
m_wndFilePathBar.SetOnFileSelectedCallback([&](int pane, const String& sFilepath) {
m_pMergeDoc->ChangeFile(pane, sFilepath);
});
// Set filename bars inactive so colors get initialized
for (nPane = 0; nPane < m_pMergeDoc->m_nBuffers; nPane++)
m_wndFilePathBar.SetActive(nPane, false);
CHexMergeView *pView[3];
for (nPane = 0; nPane < m_pMergeDoc->m_nBuffers; nPane++)
pView[nPane] = static_cast<CHexMergeView *>(m_wndSplitter.GetPane(SWAPPARAMS_IF(bSplitVert, 0, nPane)));
for (nPane = 0; nPane < m_pMergeDoc->m_nBuffers; nPane++)
CreateHexWndStatusBar(m_wndStatusBar[nPane], pView[nPane]);
CSize size = m_wndStatusBar[0].CalcFixedLayout(TRUE, TRUE);
m_rectBorder.bottom = size.cy;
// get the IHexEditorWindow interfaces
IHexEditorWindow *pif[3];
for (nPane = 0; nPane < m_pMergeDoc->m_nBuffers; nPane++)
{
pif[nPane] = reinterpret_cast<IHexEditorWindow *>(
::GetWindowLongPtr(pView[nPane]->m_hWnd, GWLP_USERDATA));
}
// tell the heksedit controls about each other
if (m_pMergeDoc->m_nBuffers == 2)
{
pif[0]->set_sibling(pif[1]);
pif[1]->set_sibling(pif[0]);
pif[1]->share_undorecords(pif[0]->share_undorecords(nullptr));
}
else if (m_pMergeDoc->m_nBuffers > 2)
{
pif[0]->set_sibling(pif[1]);
pif[1]->set_sibling2(pif[0], pif[2]);
pif[2]->set_sibling(pif[1]);
pif[2]->share_undorecords(
pif[1]->share_undorecords(
pif[0]->share_undorecords(nullptr)));
}
// tell merge doc about these views
m_pMergeDoc = dynamic_cast<CHexMergeDoc *>(pContext->m_pCurrentDoc);
m_pMergeDoc->SetMergeViews(pView);
m_pMergeDoc->RefreshOptions();
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CHexMergeFrame message handlers
void CHexMergeFrame::ActivateFrame(int nCmdShow)
{
CMergeFrameCommon::ActivateFrame(nCmdShow);
}
/**
* @brief Save the window's position, free related resources, and destroy the window
*/
BOOL CHexMergeFrame::DestroyWindow()
{
SavePosition();
SaveActivePane();
SaveWindowState();
CFrameWnd* pParentFrame = GetParentFrame();
BOOL result = CMergeFrameCommon::DestroyWindow();
if (pParentFrame)
pParentFrame->OnUpdateFrameTitle(FALSE);
return result;
}
/**
* @brief Save coordinates of the frame, splitters, and bars
*
* @note Do not save the maximized/restored state here. We are interested
* in the state of the active frame, and maybe this frame is not active
*/
void CHexMergeFrame::SavePosition()
{
}
void CHexMergeFrame::SaveActivePane()
{
if (CWnd* pLeft = m_wndSplitter.GetPane(0, 0))
{
GetOptionsMgr()->SaveOption(OPT_ACTIVE_PANE, GetActivePane());
}
}
void CHexMergeFrame::OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd, CWnd* pDeactivateWnd)
{
CMDIChildWnd::OnMDIActivate(bActivate, pActivateWnd, pDeactivateWnd);
CHexMergeDoc *pDoc = GetMergeDoc();
if (bActivate && pDoc != nullptr)
this->GetParentFrame()->PostMessage(WM_USER+1);
return;
}
void CHexMergeFrame::OnSize(UINT nType, int cx, int cy)
{
CMDIChildWnd::OnSize(nType, cx, cy);
UpdateHeaderSizes();
}
/// update splitting position for panels 1/2 and headerbar and statusbar
void CHexMergeFrame::UpdateHeaderSizes()
{
if (!m_wndSplitter.m_hWnd || !m_wndFilePathBar.m_hWnd)
return;
CRect rcFrame;
GetClientRect(&rcFrame);
int w[3],wmin;
int nPaneCount = m_wndSplitter.GetColumnCount();
if (nPaneCount > 1)
{
for (int pane = 0; pane < nPaneCount; pane++)
{
m_wndSplitter.GetColumnInfo(pane, w[pane], wmin);
if (w[pane]<1) w[pane]=1; // Perry 2003-01-22 (I don't know why this happens)
}
}
else
{
nPaneCount = m_wndSplitter.GetRowCount();
for (int pane = 0; pane < nPaneCount; pane++)
{
w[pane] = rcFrame.Width() / nPaneCount;
if (w[pane]<1) w[pane]=1; // Perry 2003-01-22 (I don't know why this happens)
}
}
if (!std::equal(m_nLastSplitPos, m_nLastSplitPos + nPaneCount, w))
{
std::copy_n(w, nPaneCount, m_nLastSplitPos);
// resize controls in header dialog bar
m_wndFilePathBar.Resize(w);
RECT rc = rcFrame;
rc.top = rc.bottom - m_rectBorder.bottom;
rc.right = 0;
for (int pane = 0; pane < nPaneCount; pane++)
{
if (pane < nPaneCount - 1)
rc.right += w[pane] + 6;
else
rc.right = rcFrame.right;
m_wndStatusBar[pane].MoveWindow(&rc);
rc.left = rc.right;
}
}
}
void CHexMergeFrame::UpdateAutoPaneResize()
{
m_wndSplitter.AutoResizePanes(GetOptionsMgr()->GetBool(OPT_RESIZE_PANES));
}
void CHexMergeFrame::UpdateSplitter()
{
m_wndSplitter.RecalcLayout();
}
int CHexMergeFrame::GetActivePane()
{
int nPane;
if (m_wndSplitter.GetColumnCount() > 1)
m_wndSplitter.GetActivePane(nullptr, &nPane);
else
m_wndSplitter.GetActivePane(&nPane, nullptr);
return nPane;
}
void CHexMergeFrame::SetActivePane(int nPane)
{
if (m_wndSplitter.GetColumnCount() > 1)
m_wndSplitter.SetActivePane(0, nPane);
else
m_wndSplitter.SetActivePane(nPane, 0);
}
/**
* @brief Synchronize control and status bar placements with splitter position,
* update mod indicators, synchronize scrollbars
*/
void CHexMergeFrame::OnIdleUpdateCmdUI()
{
if (IsWindowVisible())
{
UpdateHeaderSizes();
int pane;
int nColumns = m_wndSplitter.GetColumnCount();
CHexMergeView *pView[3] = {0};
for (pane = 0; pane < nColumns; ++pane)
pView[pane] = static_cast<CHexMergeView *>(m_wndSplitter.GetPane(0, pane));
// Update mod indicators
tchar_t ind[2];
for (pane = 0; pane < nColumns; ++pane)
{
if (m_wndFilePathBar.GetDlgItemText(IDC_STATIC_TITLE_PANE0 + pane, ind, 2))
if (pView[pane]->GetModified() ? ind[0] != _T('*') : ind[0] == _T('*'))
m_pMergeDoc->UpdateHeaderPath(pane);
}
// Synchronize scrollbars
SCROLLINFO si, siView[3];
// Synchronize horizontal scrollbars
pView[0]->GetScrollInfo(SB_HORZ, &si, SIF_ALL | SIF_DISABLENOSCROLL);
m_HScrollInfo[0] = siView[0] = si;
for (pane = 1; pane < nColumns; ++pane)
{
SCROLLINFO siCur;
pView[pane]->GetScrollInfo(SB_HORZ, &siCur, SIF_ALL | SIF_DISABLENOSCROLL);
siView[pane] = siCur;
if (si.nMin > siCur.nMin)
si.nMin = siCur.nMin;
if (si.nPage < siCur.nPage)
si.nPage = siCur.nPage;
if (si.nMax < siCur.nMax)
si.nMax = siCur.nMax;
if (memcmp(&siCur, &m_HScrollInfo[pane], sizeof si))
{
si.nPos = siCur.nPos;
si.nTrackPos = siCur.nTrackPos;
}
m_HScrollInfo[pane] = siCur;
}
for (pane = 0; pane < nColumns; ++pane)
{
if (memcmp(&si, &siView[pane], sizeof si))
{
pView[pane]->SetScrollInfo(SB_HORZ, &si);
pView[pane]->SendMessage(WM_HSCROLL, MAKEWPARAM(SB_THUMBTRACK, si.nTrackPos));
}
}
for (pane = 0; pane < nColumns; ++pane)
m_wndSplitter.GetScrollBarCtrl(pView[pane], SB_HORZ)->SetScrollInfo(&si);
// Synchronize vertical scrollbars
pView[0]->GetScrollInfo(SB_VERT, &si, SIF_ALL | SIF_DISABLENOSCROLL);
m_VScrollInfo[0] = siView[0] = si;
for (pane = 1; pane < nColumns; ++pane)
{
SCROLLINFO siCur;
pView[pane]->GetScrollInfo(SB_VERT, &siCur, SIF_ALL | SIF_DISABLENOSCROLL);
siView[pane] = siCur;
if (si.nMin > siCur.nMin)
si.nMin = siCur.nMin;
if (si.nMax < siCur.nMax)
si.nMax = siCur.nMax;
if (memcmp(&siCur, &m_VScrollInfo[pane], sizeof si))
{
si.nPos = siCur.nPos;
si.nTrackPos = siCur.nTrackPos;
}
m_VScrollInfo[pane] = siCur;
}
for (pane = 0; pane < nColumns; ++pane)
{
if (memcmp(&si, &siView[pane], sizeof si))
{
pView[pane]->SetScrollInfo(SB_VERT, &si);
pView[pane]->SendMessage(WM_VSCROLL, MAKEWPARAM(SB_THUMBTRACK, si.nTrackPos));
}
}
if (nColumns > 0)
m_wndSplitter.GetScrollBarCtrl(pView[nColumns - 1], SB_VERT)->SetScrollInfo(&si);
}
CMDIChildWnd::OnIdleUpdateCmdUI();
}
/**
* @brief Update any resources necessary after a GUI language change
*/
void CHexMergeFrame::UpdateResources()
{
}
/**
* @brief Save pane sizes and positions when one of panes requests it.
*/
LRESULT CHexMergeFrame::OnStorePaneSizes(WPARAM wParam, LPARAM lParam)
{
SavePosition();
return 0;
}
/**
* @brief Split panes vertically
*/
void CHexMergeFrame::OnViewSplitVertically()
{
bool bSplitVertically = (m_wndSplitter.GetColumnCount() != 1);
bSplitVertically = !bSplitVertically; // toggle
GetOptionsMgr()->SaveOption(OPT_SPLIT_HORIZONTALLY, !bSplitVertically);
m_wndSplitter.FlipSplit();
}
/**
* @brief Update "Split Vertically" UI items
*/
void CHexMergeFrame::OnUpdateViewSplitVertically(CCmdUI* pCmdUI)
{
pCmdUI->Enable(TRUE);
pCmdUI->SetCheck((m_wndSplitter.GetColumnCount() != 1));
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/mirrors/WinMerge.git
git@gitee.com:mirrors/WinMerge.git
mirrors
WinMerge
WinMerge
master

搜索帮助