diff --git a/src/README.md b/src/README.md new file mode 100644 index 0000000..8430625 --- /dev/null +++ b/src/README.md @@ -0,0 +1,106 @@ + +##### 说明 + +硬盘上的一份截图代码,作者是[sudami](https://bbs.pediy.com/thread-54302.htm)。 + +提取了里面的3个类CatchScreenDlg、MyTracker.h,MyEdit,自己在实现下。 + +双缓冲,完美无闪烁。 + +##### 截图 + +![snatshot.png](snatshot.png) + + +##### 说明 + +1、重写了MyEdit的绘制,避免闪烁。 + +2、修改CCatchScreenDlg中部分逻辑,避免闪烁 + +3、增加ToolBar控件,仿QQ截图界面。按钮实际功能未开发。 + +4、实现截图飞选中区域暗色处理 + + +##### ToolBar控件消息处理 + +```c++ +BOOL CCatchScreenDlg::OnCommand(WPARAM wParam, LPARAM lParam) +{ + bool bHandle = true; + HWND hWnd = m_toolBar.GetHWND(); + if(lParam == (LPARAM)m_toolBar.GetHWND()) + { + int wmId = LOWORD(wParam); + switch(wmId) + { + case MyToolBar_ID: + AfxMessageBox(_T("矩形")); + break; + case MyToolBar_ID+1: + AfxMessageBox(_T("圆形")); + break; + case MyToolBar_ID +2: + AfxMessageBox(_T("画笔")); + break; + case MyToolBar_ID +3: + AfxMessageBox(_T("马赛克")); + break; + case MyToolBar_ID +4: + AfxMessageBox(_T("文字")); + break; + case MyToolBar_ID +5: + AfxMessageBox(_T("撤销")); + break; + case MyToolBar_ID +6: + CopyScreenToBitmap(m_rectTracker.m_rect, TRUE); + PostQuitMessage(0); + break; + case MyToolBar_ID +7: + PostQuitMessage(0); + break; + case MyToolBar_ID +8: + CopyScreenToBitmap(m_rectTracker.m_rect, TRUE); + PostQuitMessage(0); + break; + default: + bHandle = false; + break; + } + ::SetFocus(hWnd); + } + if (bHandle == false) + { + return CDialog::OnCommand(wParam,lParam); + } +} +``` + + +##### 神奇的非选中区域暗色处理算法 + +```c++ + Gdiplus::Graphics graphics(dcCompatible); + + HRGN hgn1 = CreateRectRgn(m_rectTracker.m_rect.left,m_rectTracker.m_rect.top, + m_rectTracker.m_rect.right,m_rectTracker.m_rect.bottom); + Region region1(hgn1); + + HRGN hgn2 = CreateRectRgn(rect.left,rect.top, + rect.right,rect.bottom); + Region region2(hgn2); + + region2.Exclude(®ion1); + + SolidBrush solidBrush(Color(100, 128, 128, 128)); + graphics.FillRegion(&solidBrush,®ion2); + + DeleteObject(hgn1); + DeleteObject(hgn2); +``` + + + + + diff --git a/src/Release/Screenshot.exe b/src/Release/Screenshot.exe new file mode 100644 index 0000000..771fb85 Binary files /dev/null and b/src/Release/Screenshot.exe differ diff --git a/src/Screenshot.sln b/src/Screenshot.sln new file mode 100644 index 0000000..732cc79 --- /dev/null +++ b/src/Screenshot.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Screenshot", "Screenshot\Screenshot.vcproj", "{24E39ACB-AB81-485D-8D36-749B3F5EC1E8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {24E39ACB-AB81-485D-8D36-749B3F5EC1E8}.Debug|Win32.ActiveCfg = Debug|Win32 + {24E39ACB-AB81-485D-8D36-749B3F5EC1E8}.Debug|Win32.Build.0 = Debug|Win32 + {24E39ACB-AB81-485D-8D36-749B3F5EC1E8}.Release|Win32.ActiveCfg = Release|Win32 + {24E39ACB-AB81-485D-8D36-749B3F5EC1E8}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/Screenshot/CatchScreenDlg.cpp b/src/Screenshot/CatchScreenDlg.cpp new file mode 100644 index 0000000..729bc5e --- /dev/null +++ b/src/Screenshot/CatchScreenDlg.cpp @@ -0,0 +1,679 @@ +/****************************************************************************** +* FileName : CatchScreenDlg.cpp +* Author : Unknown +* Mender : sudami +* Time : 2007/09/09 +* +* Comment : +* +******************************************************************************/ + +#include "stdafx.h" +#include "Screenshot.h" +#include "CatchScreenDlg.h" + +#include +using namespace Gdiplus; + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// CCatchScreenDlg dialog + +CCatchScreenDlg::CCatchScreenDlg(CWnd* pParent /*=NULL*/) +: CDialog(CCatchScreenDlg::IDD, pParent) +{ + m_bLBtnDown = FALSE; + //ʼƤ,resizeMiddle + m_rectTracker.m_nStyle = CMyTracker::resizeMiddle | CMyTracker::solidLine; + m_rectTracker.m_rect.SetRect(-1, -2, -3, -4); + //þɫ + m_rectTracker.SetRectColor(RGB(10, 100, 130)); + + m_hCursor = AfxGetApp()->LoadCursor(IDC_CURSOR1); + + m_bDraw = FALSE; + m_bFirstDraw = FALSE; + m_bQuit = FALSE; + m_bNeedShowMsg = FALSE; + m_startPt = 0; + + //ȡĻֱ + m_xScreen = GetSystemMetrics(SM_CXSCREEN); + m_yScreen = GetSystemMetrics(SM_CYSCREEN); + + //ȡĻλͼ + CRect rect(0, 0, m_xScreen, m_yScreen); + m_hBitmap = CopyScreenToBitmap(&rect); + m_pBitmap = CBitmap::FromHandle(m_hBitmap); + + //ʼˢ´ m_rgn + m_rgn.CreateRectRgn(0, 0, 50, 50); +} + +void CCatchScreenDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Control(pDX, IDC_EDIT1, m_tipEdit); +} + +BEGIN_MESSAGE_MAP(CCatchScreenDlg, CDialog) + ON_WM_PAINT() + ON_WM_MOUSEMOVE() + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_LBUTTONDBLCLK() + ON_WM_ERASEBKGND() + ON_WM_SETCURSOR() + ON_WM_RBUTTONUP() + ON_WM_CTLCOLOR() + ON_WM_RBUTTONDOWN() +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CCatchScreenDlg message handlers + +BOOL CCatchScreenDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + //ѶԻóȫ㴰 + SetWindowPos(&wndTopMost, 0, 0, m_xScreen, m_yScreen, SWP_SHOWWINDOW); + + //ƶʾ + CRect rect; + m_tipEdit.GetWindowRect(&rect); + m_tipEdit.MoveWindow(10, 10, rect.Width(), rect.Height()); + + + m_toolBar.CreateToolBar(m_hWnd); + m_toolBar.RemoveChildStyle(); + ::MoveWindow(m_toolBar.GetHWND(),300,300,230,30,FALSE); + + + UpdateTipString(); + SetEidtWndText(); + + ((CScreenshotApp *)AfxGetApp())->m_hwndDlg = AfxGetMainWnd()->GetSafeHwnd(); + return TRUE; +} + +void CCatchScreenDlg::OnPaint() +{ + // С״̬ + if (IsIconic()) + { + CPaintDC dc(this); + + SendMessage(WM_ICONERASEBKGND, (WPARAM)dc.GetSafeHdc(), 0); + + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + } + else // ʾ + { + CPaintDC dc(this); + + CDC dcCompatible; + + dcCompatible.CreateCompatibleDC(&dc); + RECT rect; + ::GetClientRect(m_hWnd, &rect); + HBITMAP hBitmap = ::CreateCompatibleBitmap(dc.m_hDC,rect.right-rect.left,rect.bottom-rect.top); + ::SelectObject(dcCompatible.m_hDC,hBitmap); + + HBRUSH s_hBitmapBrush = CreatePatternBrush(m_hBitmap); + ::FillRect(dcCompatible.m_hDC,&rect,s_hBitmapBrush); + + //ʾȡδСϢ + if (m_bNeedShowMsg && m_bFirstDraw) + { + CRect rect = m_rectTracker.m_rect; + DrawMessage(rect, &dcCompatible); + } + + //Ƥ + if (m_bFirstDraw) + { + m_rectTracker.Draw(&dcCompatible); + } + Gdiplus::Graphics graphics(dcCompatible); + + HRGN hgn1 = CreateRectRgn(m_rectTracker.m_rect.left,m_rectTracker.m_rect.top, + m_rectTracker.m_rect.right,m_rectTracker.m_rect.bottom); + Region region1(hgn1); + + HRGN hgn2 = CreateRectRgn(rect.left,rect.top, + rect.right,rect.bottom); + Region region2(hgn2); + + region2.Exclude(®ion1); + + SolidBrush solidBrush(Color(100, 128, 128, 128)); + graphics.FillRegion(&solidBrush,®ion2); + + DeleteObject(hgn1); + DeleteObject(hgn2); + + dc.BitBlt(0,0,rect.right, rect.bottom,&dcCompatible,0,0,SRCCOPY); + DeleteObject(hBitmap); + DeleteObject(s_hBitmapBrush); + + //CDialog::OnPaint(); + } +} + +void CCatchScreenDlg::OnCancel() +{ + if (m_bFirstDraw) + { + //ȡѻα + m_bFirstDraw = FALSE; + m_bDraw = FALSE; + m_rectTracker.m_rect.SetRect(-1, -1, -1, -1); + InvalidateRgnWindow(); + } + else + { + CDialog::OnCancel(); + } +} + +void CCatchScreenDlg::OnMouseMove(UINT nFlags, CPoint point) +{ + if(m_bLBtnDown) + m_toolBar.HideToolBar(); + else + m_toolBar.ShowToolBar(); + if (m_bDraw) + { + //̬δС,ˢ» + m_rectTracker.m_rect.SetRect(m_startPt.x + 4, m_startPt.y + 4, point.x, point.y); + InvalidateRgnWindow(); + } + + //ֲСλʱ,ղMouseMoveϢ + CRect rect; + m_tipEdit.GetWindowRect(&rect); + if (rect.PtInRect(point)) + m_tipEdit.SendMessage(WM_MOUSEMOVE); + + UpdateMousePointRGBString(); + SetEidtWndText(); + + CDialog::OnMouseMove(nFlags, point); +} + +void CCatchScreenDlg::OnLButtonDown(UINT nFlags, CPoint point) +{ + m_bLBtnDown = TRUE; + int nHitTest; + nHitTest = m_rectTracker.HitTest(point); + //жϻλ + if (nHitTest < 0) + { + if (!m_bFirstDraw) + { + //һλ + m_startPt = point; + m_bDraw = TRUE; + m_bFirstDraw = TRUE; + //õ갴ʱСľδС + m_rectTracker.m_rect.SetRect(point.x, point.y, point.x + 4, point.y + 4); + + //֤굱ʱʾϢ + if (m_bFirstDraw) + m_bNeedShowMsg = TRUE; + UpdateTipString(); + SetEidtWndText(); + InvalidateRgnWindow(); + } + } + else + { + //֤굱ʱʾϢ + m_bNeedShowMsg = TRUE; + if (m_bFirstDraw) + { + //Сʱ,TrackԶδС,Щڼ,ϢCRectTrackerڲ + m_rectTracker.Track(this, point, TRUE); + InvalidateRgnWindow(); + } + } + + CDialog::OnLButtonDown(nFlags, point); +} + +void CCatchScreenDlg::OnLButtonUp(UINT nFlags, CPoint point) +{ + m_bLBtnDown = FALSE; + m_bNeedShowMsg = FALSE; + m_bDraw = FALSE; + UpdateTipString(); + SetEidtWndText(); + m_toolBar.SetShowPlace(m_rectTracker.m_rect.right,m_rectTracker.m_rect.bottom); + + InvalidateRgnWindow(); + CDialog::OnLButtonUp(nFlags, point); +} + +void CCatchScreenDlg::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + int nHitTest; + nHitTest = m_rectTracker.HitTest(point); + + //Ǿڲ˫ + if (nHitTest == 8) + { + //λͼճ,bSave ΪTRUE, + CopyScreenToBitmap(m_rectTracker.m_rect, TRUE); + PostQuitMessage(0); + } + + CDialog::OnLButtonDblClk(nFlags, point); +} + +void CCatchScreenDlg::OnRButtonDown(UINT nFlags, CPoint point) +{ + m_toolBar.HideToolBar(); + //InvalidateRgnWindow(); + CDialog::OnRButtonDown(nFlags, point); +} + +void CCatchScreenDlg::OnRButtonUp(UINT nFlags, CPoint point) +{ + m_bLBtnDown = FALSE; + if (m_bFirstDraw) + { + //Ѿȡȡ + m_bFirstDraw = FALSE; + //δС + m_rectTracker.m_rect.SetRect(-1, -1, -1, -1); + UpdateTipString(); + SetEidtWndText(); + InvalidateRgnWindow(); + } + else + { + //رճ + PostQuitMessage(0); + } + + CDialog::OnRButtonUp(nFlags, point); +} + +HBRUSH CCatchScreenDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) +{ + HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); + + //òʾıɫ + if (pWnd->GetDlgCtrlID() == IDC_EDIT1) + { + pDC->SetTextColor(RGB(247,76,128)); + } + + return hbr; +} + +BOOL CCatchScreenDlg::OnEraseBkgnd(CDC* pDC) +{ + return FALSE; + //ȫԻ򱳾 + BITMAP bmp; + m_pBitmap->GetBitmap(&bmp); + + CDC dcCompatible; + dcCompatible.CreateCompatibleDC(pDC); + + dcCompatible.SelectObject(m_pBitmap); + + CRect rect; + GetClientRect(&rect); + pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &dcCompatible, 0, 0, SRCCOPY); + return TRUE; +} + +BOOL CCatchScreenDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) +{ + //øıȡδСʱ + if (pWnd == this &&m_rectTracker.SetCursor(this, nHitTest) + && !m_bDraw &&m_bFirstDraw) //˴жϱȡʱʼΪɫ + { + return TRUE; + } + + //òɫ + SetCursor(m_hCursor); + return TRUE; +} + +// Ļ, ԴԴCSDN +// lpRect ѡ +HBITMAP CCatchScreenDlg::CopyScreenToBitmap(LPRECT lpRect, BOOL bSave) + +{ + HDC hScrDC, hMemDC; + // Ļڴ豸 + HBITMAP hBitmap, hOldBitmap; + // λͼ + int nX, nY, nX2, nY2; + // ѡ + int nWidth, nHeight; + + // ȷѡΪվ + if (IsRectEmpty(lpRect)) + return NULL; + //ΪĻ豸 + hScrDC = CreateDC(_T("DISPLAY"), NULL, NULL, NULL); + + //ΪĻ豸ݵڴ豸 + hMemDC = CreateCompatibleDC(hScrDC); + // ѡ + nX = lpRect->left; + nY = lpRect->top; + nX2 = lpRect->right; + nY2 = lpRect->bottom; + + //ȷѡǿɼ + if (nX < 0) + nX = 0; + if (nY < 0) + nY = 0; + if (nX2 > m_xScreen) + nX2 = m_xScreen; + if (nY2 > m_yScreen) + nY2 = m_yScreen; + nWidth = nX2 - nX; + nHeight = nY2 - nY; + // һĻ豸ݵλͼ + hBitmap = CreateCompatibleBitmap + (hScrDC, nWidth, nHeight); + // λͼѡڴ豸 + hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); + // Ļ豸ڴ豸 + if (bSave) + { + //DC,bSaveΪʱѿʼȫλͼ,ȡδС + CDC dcCompatible; + dcCompatible.CreateCompatibleDC(CDC::FromHandle(hMemDC)); + dcCompatible.SelectObject(m_pBitmap); + + BitBlt(hMemDC, 0, 0, nWidth, nHeight, + dcCompatible, nX, nY, SRCCOPY); + } + else + { + BitBlt(hMemDC, 0, 0, nWidth, nHeight, + hScrDC, nX, nY, SRCCOPY); + } + + hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap); + //õĻλͼľ + // + DeleteDC(hScrDC); + DeleteDC(hMemDC); + + if (bSave) + { + if (OpenClipboard()) + { + //ռ + EmptyClipboard(); + //Ļճ, + //hBitmap ΪղŵĻλͼ + SetClipboardData(CF_BITMAP, hBitmap); + //رռ + CloseClipboard(); + } + } + // λͼ + return hBitmap; +} + +// ʾʾϢ +void CCatchScreenDlg::UpdateTipString() +{ + CString strTemp; + if (!m_bDraw && !m_bFirstDraw) + { + strTemp = _T("\r\n\r\nѡȡ\r\n\r\nESCҼ˳"); + } + else + if (m_bDraw && m_bFirstDraw) + { + strTemp = _T("\r\n\r\nɿȷȡΧ\r\n\r\nESC˳"); + } + else if (!m_bDraw && m_bFirstDraw) + { + CString sudami(_T("\r\n\r\n˫\r\n\r\nҼѡ")); + strTemp = _T("\r\n\r\nھαԵС"); + + strTemp += sudami; + } + m_strEditTip = strTemp; +} + +// ʾȡϢ +void CCatchScreenDlg::DrawMessage(CRect &inRect, CDC * pDC) +{ + //ȡδСϢ + const int space = 3; + + //ɫС + CPoint pt; + CPen pen(PS_SOLID, 1, RGB(47, 79, 79)); + CPen *pOldPen; + pOldPen = pDC->SelectObject(&pen); + + //pDC->SetTextColor(RGB(147,147,147)); + CFont font; + CFont * pOldFont; + font.CreatePointFont(90, _T("")); + pOldFont = pDC->SelectObject(&font); + + //õȺ͸߶ + GetCursorPos(&pt); + int OldBkMode; + OldBkMode = pDC->SetBkMode(TRANSPARENT); + + TEXTMETRIC tm; + int charHeight; + CSize size; + int lineLength; + pDC->GetTextMetrics(&tm); + charHeight = tm.tmHeight + tm.tmExternalLeading; + size = pDC->GetTextExtent(_T("λ "), _tcslen(_T("λ "))); + lineLength = size.cx; + + //ʼ, Ա֤д + CRect rect(pt.x + space, pt.y - charHeight * 6 - space, pt.x + lineLength + space, pt.y - space); + + //ʱ + CRect rectTemp; + //εԵʱʹС + if ((pt.x + rect.Width()) >= m_xScreen) + { + //Ϸʾ¾ + rectTemp = rect; + rectTemp.left = rect.left - rect.Width() - space * 2; + rectTemp.right = rect.right - rect.Width() - space * 2;; + rect = rectTemp; + } + + if ((pt.y - rect.Height()) <= 0) + { + //ҷʾ¾ + rectTemp = rect; + rectTemp.top = rect.top + rect.Height() + space * 2;; + rectTemp.bottom = rect.bottom + rect.Height() + space * 2;; + rect = rectTemp; + } + + //ջˢ + CBrush * pOldBrush; + pOldBrush = pDC->SelectObject(CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH))); + + pDC->Rectangle(rect); + rect.top += 2; + //ھʾ + CRect outRect(rect.left, rect.top, rect.left + lineLength, rect.top + charHeight); + CString string(_T("λ")); + pDC->DrawText(string, outRect, DT_CENTER); + + outRect.SetRect(rect.left, rect.top + charHeight, rect.left + lineLength, charHeight + rect.top + charHeight); + string.Format(_T("(%d,%d)"), inRect.left, inRect.top); + pDC->DrawText(string, outRect, DT_CENTER); + + + outRect.SetRect(rect.left, rect.top + charHeight * 2, rect.left + lineLength, charHeight + rect.top + charHeight * 2); + string = _T("δС"); + pDC->DrawText(string, outRect, DT_CENTER); + + outRect.SetRect(rect.left, rect.top + charHeight * 3, rect.left + lineLength, charHeight + rect.top + charHeight * 3); + string.Format(_T("(%d,%d)"), inRect.Width(), inRect.Height()); + pDC->DrawText(string, outRect, DT_CENTER); + + outRect.SetRect(rect.left, rect.top + charHeight * 4, rect.left + lineLength, charHeight + rect.top + charHeight * 4); + string = _T(""); + pDC->DrawText(string, outRect, DT_CENTER); + + outRect.SetRect(rect.left, rect.top + charHeight * 5, rect.left + lineLength, charHeight + rect.top + charHeight * 5); + string.Format(_T("(%d,%d)"), pt.x, pt.y); + pDC->DrawText(string, outRect, DT_CENTER); + + pDC->SetBkMode(OldBkMode); + pDC->SelectObject(pOldFont); + pDC->SelectObject(pOldBrush); + pDC->SelectObject(pOldPen); +} + +// ˢ¾ֲ +void CCatchScreenDlg::InvalidateRgnWindow() +{ + //ȡȫԻ򴰿ڴС + CRect rect1; + GetWindowRect(rect1); + + //ȡ༭򴰿ڴС + CRect rect2; + m_tipEdit.GetWindowRect(rect2); + + CRgn rgn1, rgn2; + rgn1.CreateRectRgnIndirect(rect1); + rgn2.CreateRectRgnIndirect(rect2); + + //ȡ,dz˱༭򴰿ڲ + //m_rgn.CombineRgn(&rgn1, &rgn2, RGN_DIFF); + + // ToolBarˢ + CRect rect3; + ::GetWindowRect(m_toolBar.GetHWND(),&rect3); + CRgn rgn3; + rgn3.CreateRectRgnIndirect(rect3); + + CRgn rgnTemp; + rgnTemp.CreateRectRgn(0, 0, 50, 50); + rgnTemp.CombineRgn(&rgn1, &rgn2, RGN_DIFF); + m_rgn.CombineRgn(&rgnTemp, &rgn3, RGN_DIFF); + + InvalidateRgn(&m_rgn); +} + +void CCatchScreenDlg::UpdateMousePointRGBString() +{ + static CString strOld(""); + + CPoint pt; + GetCursorPos(&pt); + + COLORREF color; + CClientDC dc(this); + color = dc.GetPixel(pt); + BYTE rValue, gValue, bValue; + rValue = GetRValue(color); + gValue = GetGValue(color); + bValue = GetGValue(color); + + //ʽŷַ + CString string; + string.Format(_T("\r\n\r\nǰRGB(%d,%d,%d)"), rValue, gValue, bValue); + + //ǰɫûˢRGBֵ,ⴰи˸ + if (strOld != string) + { + m_strRgb = string; + } + strOld = string; +} + +void CCatchScreenDlg::SetEidtWndText() +{ + m_tipEdit.SetWindowText(this->GetEditText()); +} + +CString CCatchScreenDlg::GetEditText() +{ + CString str; + str.Append(m_strRgb); + str.Append(m_strEditTip); + return str; +} + +BOOL CCatchScreenDlg::OnCommand(WPARAM wParam, LPARAM lParam) +{ + bool bHandle = true; + HWND hWnd = m_toolBar.GetHWND(); + if(lParam == (LPARAM)m_toolBar.GetHWND()) + { + int wmId = LOWORD(wParam); + switch(wmId) + { + case MyToolBar_ID: + AfxMessageBox(_T("")); + break; + case MyToolBar_ID+1: + AfxMessageBox(_T("Բ")); + break; + case MyToolBar_ID +2: + AfxMessageBox(_T("")); + break; + case MyToolBar_ID +3: + AfxMessageBox(_T("")); + break; + case MyToolBar_ID +4: + AfxMessageBox(_T("")); + break; + case MyToolBar_ID +5: + AfxMessageBox(_T("")); + break; + case MyToolBar_ID +6: + CopyScreenToBitmap(m_rectTracker.m_rect, TRUE); + PostQuitMessage(0); + break; + case MyToolBar_ID +7: + PostQuitMessage(0); + break; + case MyToolBar_ID +8: + CopyScreenToBitmap(m_rectTracker.m_rect, TRUE); + PostQuitMessage(0); + break; + default: + bHandle = false; + break; + } + ::SetFocus(hWnd); + } + if (bHandle == false) + { + return CDialog::OnCommand(wParam,lParam); + } +} + +////////////////////////////////// END OF FILE /////////////////////////////////////// \ No newline at end of file diff --git a/src/Screenshot/CatchScreenDlg.h b/src/Screenshot/CatchScreenDlg.h new file mode 100644 index 0000000..25c31d2 --- /dev/null +++ b/src/Screenshot/CatchScreenDlg.h @@ -0,0 +1,90 @@ +#if !defined(AFX_CATCHSCREENDLG_H__536FDBC8_7DB2_4BEF_8943_70DBE8AD845F__INCLUDED_) +#define AFX_CATCHSCREENDLG_H__536FDBC8_7DB2_4BEF_8943_70DBE8AD845F__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +//-------------------------------------------------------------------------- +#include "Resource.h" +#include "MyEdit.h" + +#ifndef MYTRACKER_ +#include "MyTracker.h" +#endif + +#include "MyToolBar.h" +//-------------------------------------------------------------------------- + +///////////////////////////////////////////////////////////////////////////// +// +class CCatchScreenDlg : public CDialog +{ +public: + + CCatchScreenDlg(CWnd* pParent = NULL); + + enum { IDD = IDD_DIALOGFORIMG }; + CMyEdit m_tipEdit; + CMyToolBar m_toolBar; + +public: + + int m_xScreen; + int m_yScreen; + + + BOOL m_bLBtnDown; + + BOOL m_bNeedShowMsg; // ʾȡδСϢ + BOOL m_bDraw; // ǷΪȡ״̬ + BOOL m_bFirstDraw; // ǷΪ״νȡ + BOOL m_bQuit; // ǷΪ˳ + CPoint m_startPt; // ȡϽλ + + CMyTracker m_rectTracker; // Ƥ + CBrush m_brush; + HCURSOR m_hCursor; // + CBitmap* m_pBitmap; // Editؼıλͼ + HBITMAP m_hBitmap; + + CRgn m_rgn; // + +public: + HBITMAP CopyScreenToBitmap(LPRECT lpRect,BOOL bSave=FALSE); /* 浽λͼ */ + void UpdateTipString(); //ʾʾϢ + void DrawMessage(CRect &inRect,CDC * pDC); //ʾȡϢ + void InvalidateRgnWindow(); //ػ + void UpdateMousePointRGBString(); + + CString m_strRgb; + CString m_strEditTip; + + void SetEidtWndText(); + CString GetEditText(); + +protected: + virtual void DoDataExchange(CDataExchange* pDX); + virtual BOOL OnInitDialog(); + virtual void OnCancel(); + + afx_msg void OnPaint(); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnRButtonUp(UINT nFlags, CPoint point); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); + afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); + + + DECLARE_MESSAGE_MAP() + + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/src/Screenshot/MyEdit.cpp b/src/Screenshot/MyEdit.cpp new file mode 100644 index 0000000..8a2d5dc --- /dev/null +++ b/src/Screenshot/MyEdit.cpp @@ -0,0 +1,120 @@ +/****************************************************************************** +* FileName : MyEdit.CPP +* Author : Unknown +* Mender : sudami +* Time : 2007/09/09 +* +* Comment : +*-------------------------------------------------------- +* ͼеһؼװ. +* ؼ͸,ʾǰͼһЩʾϢ +*-------------------------------------------------------- +******************************************************************************/ + +#include "stdafx.h" +#include "MyEdit.h" +#include "resource.h" + +/////////////////////////////////////////////////////////////////////////////// +// 캯 +// +CMyEdit::CMyEdit() +{ + m_bMove=TRUE; +} + +CMyEdit::~CMyEdit() +{ + +} + +BEGIN_MESSAGE_MAP(CMyEdit, CEdit) + /* 2СϢ */ + ON_WM_CREATE() + ON_WM_PAINT() + ON_WM_SETFOCUS() + /* 3Ϣ */ + ON_WM_MOUSEMOVE() + ON_WM_ERASEBKGND() +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// +int CMyEdit::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CEdit::OnCreate(lpCreateStruct) == -1) + return -1; + return 0; +} + + +void CMyEdit::OnPaint() +{ + CPaintDC dc(this); + + CDC dcCompatible; + dcCompatible.CreateCompatibleDC(&dc); + + dcCompatible.SetBkMode(TRANSPARENT); + CBitmap bitmap; + bitmap.LoadBitmap(IDB_BITMAP_BK); + dcCompatible.SelectObject(&bitmap); + + RECT rt = {5,5,0,0}; + RECT rtClient = {0}; + GetClientRect(&rtClient); + rt.right = rtClient.right; + rt.bottom = rtClient.bottom; + + CString str; + GetWindowText(str); + CFont font; + CFont * pOldFont; + font.CreatePointFont(90, _T("")); + pOldFont = dcCompatible.SelectObject(&font); + dcCompatible.DrawText(str,&rt,DT_LEFT); + dcCompatible.SelectObject(pOldFont); + + CRect rect; + GetClientRect(&rect); + dc.BitBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,SRCCOPY); +} + +///////////////////////////////////////////////////////////////////////////// +// <Ӧ WM_MOUSEMOVE Ϣ> +// QQĽͼЧ,ֻҪŲÿؼ,ͱ任λ +// +void CMyEdit::OnMouseMove(UINT nFlags, CPoint point) +{ + CEdit::OnMouseMove(nFlags, point); + CRect rect; + GetWindowRect(&rect); + int xScreen = GetSystemMetrics(SM_CXSCREEN); + if(m_bMove) + { + //ƶϽ + MoveWindow(10,10,rect.Width(),rect.Height()); + m_bMove=FALSE; + } + else + { + //ƶϽ + MoveWindow(xScreen-180,10,rect.Width(),rect.Height()); + m_bMove=TRUE; + } +} + +///////////////////////////////////////////////////////////////////////////// +// +void CMyEdit::OnSetFocus(CWnd* pOldWnd) +{ + CEdit::OnSetFocus(pOldWnd); + + // عʾ + this->HideCaret(); +} + +BOOL CMyEdit::OnEraseBkgnd(CDC* pDC) +{ + return TRUE; +} diff --git a/src/Screenshot/MyEdit.h b/src/Screenshot/MyEdit.h new file mode 100644 index 0000000..0245040 --- /dev/null +++ b/src/Screenshot/MyEdit.h @@ -0,0 +1,51 @@ +/***************************************************************************** +* FileName : MyEdit.h +* Author : Unknown +* Mender : sudami +* Time : 2007/09/09 +* +* Comment : +*-------------------------------------------------------- +* ͼеһؼװ. +* ؼ͸,ʾǰͼһЩʾϢ +*-------------------------------------------------------- +******************************************************************************/ + +#if !defined(AFX_MYEDIT_H__A34EEA6D_E8FC_4D15_B03C_BAA42FDF6FCB__INCLUDED_) +#define AFX_MYEDIT_H__A34EEA6D_E8FC_4D15_B03C_BAA42FDF6FCB__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +//----------------------------------------------------------------------------- + +#include + +//----------------------------------------------------------------------------- + +class CMyEdit : public CEdit +{ +public: + CMyEdit(); + virtual ~CMyEdit(); + + BOOL m_bMove; // "˫" + +protected: + + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnSetFocus(CWnd* pOldWnd); + + afx_msg void OnPaint(); + + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + + DECLARE_MESSAGE_MAP() +}; + +////////////////////////////////////////////////////////////////////////////////// + +#endif \ No newline at end of file diff --git a/src/Screenshot/MyToolBar.cpp b/src/Screenshot/MyToolBar.cpp new file mode 100644 index 0000000..46b026b --- /dev/null +++ b/src/Screenshot/MyToolBar.cpp @@ -0,0 +1,148 @@ +#include "StdAfx.h" +#include "MyToolBar.h" +#include +#include "resource.h" + + + +BOOL ImageFromIDResource(UINT nID, LPCTSTR sTR, Gdiplus::Bitmap * & pImg) +{ + HINSTANCE hInst = AfxGetResourceHandle(); + HRSRC hRsrc = ::FindResource (hInst,MAKEINTRESOURCE(nID),sTR); // type + if (!hRsrc) + return FALSE; + // load resource into memory + DWORD len = SizeofResource(hInst, hRsrc); + BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc); + if (!lpRsrc) + return FALSE; + // Allocate global memory on which to create stream + HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len); + BYTE* pmem = (BYTE*)GlobalLock(m_hMem); + memcpy(pmem,lpRsrc,len); + IStream* pstm; + CreateStreamOnHGlobal(m_hMem,FALSE,&pstm); + // load from stream + pImg=Gdiplus::Bitmap::FromStream(pstm); + // free/release stuff + GlobalUnlock(m_hMem); + pstm->Release(); + FreeResource(lpRsrc); + return TRUE; +} + +CMyToolBar::CMyToolBar() +{ + m_hImageList = NULL; + m_hWnd_toolbar = 0; + m_hWndParent = 0; +} + +CMyToolBar::~CMyToolBar(void) +{ + ImageList_Destroy(m_hImageList); +} + +BOOL CMyToolBar::CreateToolBar(HWND hWndParent) +{ + if (m_hImageList) + return FALSE; + m_hWndParent = hWndParent; + + m_hImageList= ImageList_Create(18,18,ILC_COLOR32,1,1); + Gdiplus::Bitmap * pImage = NULL; + for(int i=0;i< 9;i++) + { + ImageFromIDResource(IDB_RECTANGLE + i,_T("PNG"),pImage); + HBITMAP pHbitmap=0;; + if(pImage) + { + pImage->GetHBITMAP(Gdiplus::Color(0xff,0xff,0xff,0xff),&pHbitmap); + ImageList_Add(m_hImageList,pHbitmap,NULL); + delete pImage; + pImage = NULL; + } + } + + m_hWnd_toolbar = ::CreateWindowEx(0,TOOLBARCLASSNAME,0,WS_CHILD | WS_VISIBLE|WS_BORDER , + 0,0,0,0,hWndParent,NULL,GetModuleHandle(NULL),NULL); + + if (m_hWnd_toolbar == NULL) + return FALSE; + ::SendMessage(m_hWnd_toolbar,TB_SETIMAGELIST, 0, (LPARAM) m_hImageList); + ::SendMessage(m_hWnd_toolbar,TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); + + + ::SendMessage(m_hWnd_toolbar, + (UINT) TB_SETBITMAPSIZE,(WPARAM) 0,//not used, must be zero + (LPARAM) MAKELONG (18, 18)// = (LPARAM) MAKELONG (dxBitmap, dyBitmap) + ); + + //TCHAR tooltips[16][30]={_T("AAAA"),_T("BBBB"),_T("CCCC"),_T("DDDD")}; + for(int i = 0; i < 9; i++) + { + TBBUTTON tbbutton; + // + int wrapnow = 0; + //if (i % 2 == 1) + // wrapnow = TBSTATE_WRAP; + + ZeroMemory(&tbbutton, sizeof(TBBUTTON)); + //tbbutton.iString = (INT_PTR) tooltips[i]; + tbbutton.fsStyle = TBSTYLE_CHECKGROUP; // ѡ + tbbutton.fsState = TBSTATE_ENABLED | wrapnow; + tbbutton.idCommand = MyToolBar_ID + i; // ؼid + tbbutton.iBitmap = i; + + ::SendMessage(m_hWnd_toolbar,TB_ADDBUTTONS, 1, (LPARAM) &tbbutton); + } + ::SendMessage(m_hWnd_toolbar, TB_AUTOSIZE, 0, 0); + return TRUE; +} + +HWND CMyToolBar::GetHWND() +{ + return m_hWnd_toolbar; +} + +void CMyToolBar::AddChildStyle() +{ + DWORD dwStyle = GetWindowLong(m_hWnd_toolbar, GWL_STYLE); + dwStyle &= WS_CHILD; + SetWindowLong(m_hWnd_toolbar,GWL_STYLE,dwStyle); +} + +void CMyToolBar::RemoveChildStyle() +{ + + DWORD dwStyle = GetWindowLong(m_hWnd_toolbar, GWL_STYLE); + dwStyle &= ~WS_CHILD; + SetWindowLong(m_hWnd_toolbar,GWL_STYLE,dwStyle); +} + +void CMyToolBar::ShowToolBar() +{ + ::ShowWindow(m_hWnd_toolbar,SW_SHOW); +} + +void CMyToolBar::HideToolBar() +{ + ::ShowWindow(m_hWnd_toolbar,SW_HIDE); +} + +void CMyToolBar::SetAtCurMousePlase() +{ + RECT rtWin = {0}; + ::GetWindowRect(m_hWnd_toolbar,&rtWin); + POINT pt = {0}; + ::GetCursorPos(&pt); + this->SetShowPlace(pt.x,pt.y); +} + +void CMyToolBar::SetShowPlace(int nCurPointX,int nCurPointY) +{ + + RECT rtWin = {0}; + ::GetWindowRect(m_hWnd_toolbar,&rtWin); + ::SetWindowPos(m_hWnd_toolbar,HWND_TOP,nCurPointX - (rtWin.right-rtWin.left),nCurPointY + 2,0,0,SWP_NOSIZE|SWP_SHOWWINDOW); +} \ No newline at end of file diff --git a/src/Screenshot/MyToolBar.h b/src/Screenshot/MyToolBar.h new file mode 100644 index 0000000..645e34e --- /dev/null +++ b/src/Screenshot/MyToolBar.h @@ -0,0 +1,24 @@ +#pragma once + + +#define MyToolBar_ID 600 + +class CMyToolBar +{ +public: + CMyToolBar(); + ~CMyToolBar(void); + + BOOL CreateToolBar(HWND hWndParent); + void AddChildStyle(); + void RemoveChildStyle(); + void ShowToolBar(); + void HideToolBar(); + void SetAtCurMousePlase(); + void SetShowPlace(int nCurPointX,int nCurPointY); + HWND GetHWND(); +private: + HIMAGELIST m_hImageList; + HWND m_hWndParent; + HWND m_hWnd_toolbar; +}; diff --git a/src/Screenshot/MyTracker.cpp b/src/Screenshot/MyTracker.cpp new file mode 100644 index 0000000..5b043ae --- /dev/null +++ b/src/Screenshot/MyTracker.cpp @@ -0,0 +1,839 @@ +// This is a part of the Microsoft Foundation Classes C++ library. +// Copyright (C) 1992-1998 Microsoft Corporation +// All rights reserved. +// +// This source code is only intended as a supplement to the +// Microsoft Foundation Classes Reference and related +// electronic documentation provided with the library. +// See these sources for detailed information regarding the +// Microsoft Foundation Classes product. + +#include "stdafx.h" +#include "MyTracker.h" +#include "Resource.h" +#include "CatchScreenDlg.h" + +///////////////////////////////////////////////////////////////////////////// +// CMyTracker global state + +// various GDI objects we need to draw +AFX_STATIC_DATA HCURSOR _afxCursors[10] = { 0,}; +AFX_STATIC_DATA HBRUSH _afxHatchBrush = 0; +AFX_STATIC_DATA HPEN _afxBlackDottedPen = 0; +AFX_STATIC_DATA HPEN _afxBlackSolidPen = 0; +AFX_STATIC_DATA int _afxHandleSize = 0; + +void AFX_CDECL AfxTrackerTerm() +{ + AfxDeleteObject((HGDIOBJ*)&_afxHatchBrush); + AfxDeleteObject((HGDIOBJ*)&_afxBlackDottedPen); +} +char _afxTrackerTerm = (char)atexit(&AfxTrackerTerm); + +// the struct below is used to determine the qualities of a particular handle +struct AFX_HANDLEINFO +{ + size_t nOffsetX; // offset within RECT for X coordinate + size_t nOffsetY; // offset within RECT for Y coordinate + int nCenterX; // adjust X by Width()/2 * this number + int nCenterY; // adjust Y by Height()/2 * this number + int nHandleX; // adjust X by handle size * this number + int nHandleY; // adjust Y by handle size * this number + int nInvertX; // handle converts to this when X inverted + int nInvertY; // handle converts to this when Y inverted +}; + +// this array describes all 8 handles (clock-wise) +AFX_STATIC_DATA const AFX_HANDLEINFO _afxHandleInfo[] = +{ + // corner handles (top-left, top-right, bottom-right, bottom-left + { offsetof(RECT, left), offsetof(RECT, top), 0, 0, 0, 0, 1, 3 }, + { offsetof(RECT, right), offsetof(RECT, top), 0, 0, -1, 0, 0, 2 }, + { offsetof(RECT, right), offsetof(RECT, bottom), 0, 0, -1, -1, 3, 1 }, + { offsetof(RECT, left), offsetof(RECT, bottom), 0, 0, 0, -1, 2, 0 }, + + // side handles (top, right, bottom, left) + { offsetof(RECT, left), offsetof(RECT, top), 1, 0, 0, 0, 4, 6 }, + { offsetof(RECT, right), offsetof(RECT, top), 0, 1, -1, 0, 7, 5 }, + { offsetof(RECT, left), offsetof(RECT, bottom), 1, 0, 0, -1, 6, 4 }, + { offsetof(RECT, left), offsetof(RECT, top), 0, 1, 0, 0, 5, 7 } +}; + +// the struct below gives us information on the layout of a RECT struct and +// the relationship between its members +struct AFX_RECTINFO +{ + size_t nOffsetAcross; // offset of opposite point (ie. left->right) + int nSignAcross; // sign relative to that point (ie. add/subtract) +}; + +// this array is indexed by the offset of the RECT member / sizeof(int) +AFX_STATIC_DATA const AFX_RECTINFO _afxRectInfo[] = +{ + { offsetof(RECT, right), +1 }, + { offsetof(RECT, bottom), +1 }, + { offsetof(RECT, left), -1 }, + { offsetof(RECT, top), -1 }, +}; + +///////////////////////////////////////////////////////////////////////////// +// CMyTracker intitialization + +CMyTracker::CMyTracker(LPCRECT lpSrcRect, UINT nStyle) +{ + ASSERT(AfxIsValidAddress(lpSrcRect, sizeof(RECT), FALSE)); + + Construct(); + m_rect.CopyRect(lpSrcRect); + m_nStyle = nStyle; +} + +CMyTracker::CMyTracker() +{ + Construct(); +} + +void CMyTracker::Construct() +{ + // do one-time initialization if necessary + //******************************************************** + m_rectColor=RGB(0,0,0); + //******************************************************** + AfxLockGlobals(CRIT_RECTTRACKER); + static BOOL bInitialized; + if (!bInitialized) + { + // sanity checks for assumptions we make in the code + ASSERT(sizeof(((RECT*)NULL)->left) == sizeof(int)); + ASSERT(offsetof(RECT, top) > offsetof(RECT, left)); + ASSERT(offsetof(RECT, right) > offsetof(RECT, top)); + ASSERT(offsetof(RECT, bottom) > offsetof(RECT, right)); + + if (_afxHatchBrush == NULL) + { + // create the hatch pattern + bitmap + WORD hatchPattern[8]; + WORD wPattern = 0x1111; + for (int i = 0; i < 4; i++) + { + hatchPattern[i] = wPattern; + hatchPattern[i+4] = wPattern; + wPattern <<= 1; + } + HBITMAP hatchBitmap = CreateBitmap(8, 8, 1, 1, &hatchPattern); + if (hatchBitmap == NULL) + { + AfxUnlockGlobals(CRIT_RECTTRACKER); + AfxThrowResourceException(); + } + + // create black hatched brush + _afxHatchBrush = CreatePatternBrush(hatchBitmap); + DeleteObject(hatchBitmap); + if (_afxHatchBrush == NULL) + { + AfxUnlockGlobals(CRIT_RECTTRACKER); + AfxThrowResourceException(); + } + } + //CreatePen for DottedLine and SolidLine + CreatePen(); + + // Note: all track cursors must live in same module + HINSTANCE hInst = AfxFindResourceHandle( + MAKEINTRESOURCE(AFX_IDC_TRACK4WAY), RT_GROUP_CURSOR); + + // initialize the cursor array + _afxCursors[0] = ::LoadCursor(hInst, MAKEINTRESOURCE(AFX_IDC_TRACKNWSE)); + _afxCursors[1] = ::LoadCursor(hInst, MAKEINTRESOURCE(AFX_IDC_TRACKNESW)); + _afxCursors[2] = _afxCursors[0]; + _afxCursors[3] = _afxCursors[1]; + _afxCursors[4] = ::LoadCursor(hInst, MAKEINTRESOURCE(AFX_IDC_TRACKNS)); + _afxCursors[5] = ::LoadCursor(hInst, MAKEINTRESOURCE(AFX_IDC_TRACKWE)); + _afxCursors[6] = _afxCursors[4]; + _afxCursors[7] = _afxCursors[5]; + _afxCursors[8] = ::LoadCursor(hInst, MAKEINTRESOURCE(AFX_IDC_TRACK4WAY)); + _afxCursors[9] = ::LoadCursor(hInst, MAKEINTRESOURCE(AFX_IDC_MOVE4WAY)); + + // get default handle size from Windows profile setting + static const TCHAR szWindows[] = _T("windows"); + static const TCHAR szInplaceBorderWidth[] = + _T("oleinplaceborderwidth"); + _afxHandleSize = GetProfileInt(szWindows, szInplaceBorderWidth, 4); + bInitialized = TRUE; + } + AfxUnlockGlobals(CRIT_RECTTRACKER); + + m_nStyle = 0; + m_nHandleSize = _afxHandleSize; + m_sizeMin.cy = m_sizeMin.cx = m_nHandleSize*2; + + m_rectLast.SetRectEmpty(); + m_sizeLast.cx = m_sizeLast.cy = 0; + m_bErase = FALSE; + m_bFinalErase = FALSE; +} + +CMyTracker::~CMyTracker() +{ +} + +///////////////////////////////////////////////////////////////////////////// +// CMyTracker operations + +void CMyTracker::Draw(CDC* pDC) const +{ + // set initial DC state + VERIFY(pDC->SaveDC() != 0); + pDC->SetMapMode(MM_TEXT); + pDC->SetViewportOrg(0, 0); + pDC->SetWindowOrg(0, 0); + + // get normalized rectangle + CRect rect = m_rect; + rect.NormalizeRect(); + + CPen* pOldPen = NULL; + CBrush* pOldBrush = NULL; + CGdiObject* pTemp; + int nOldROP; + + // draw lines + if ((m_nStyle & (dottedLine|solidLine)) != 0) + { + if (m_nStyle & dottedLine) + { + //ı䵱ǰɫ + pOldPen = pDC->SelectObject(CPen::FromHandle(_afxBlackDottedPen)); + } + else + { + //ı䵱ǰɫ + //pOldPen = (CPen*)pDC->SelectStockObject(BLACK_PEN); //BLACK_PEN + pOldPen = pDC->SelectObject(CPen::FromHandle(_afxBlackSolidPen)); + } + + pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH); + nOldROP = pDC->SetROP2(R2_COPYPEN); + rect.InflateRect(+1, +1); // borders are one pixel outside + pDC->Rectangle(rect.left, rect.top, rect.right, rect.bottom); + pDC->SetROP2(nOldROP); + } + + // if hatchBrush is going to be used, need to unrealize it + if ((m_nStyle & (hatchInside|hatchedBorder)) != 0) + UnrealizeObject(_afxHatchBrush); + + // hatch inside + if ((m_nStyle & hatchInside) != 0) + { + pTemp = pDC->SelectStockObject(NULL_PEN); + if (pOldPen == NULL) + pOldPen = (CPen*)pTemp; + pTemp = pDC->SelectObject(CBrush::FromHandle(_afxHatchBrush)); + if (pOldBrush == NULL) + pOldBrush = (CBrush*)pTemp; + pDC->SetBkMode(TRANSPARENT); + nOldROP = pDC->SetROP2(R2_MASKNOTPEN); + pDC->Rectangle(rect.left+1, rect.top+1, rect.right, rect.bottom); + pDC->SetROP2(nOldROP); + } + + // draw hatched border + if ((m_nStyle & hatchedBorder) != 0) + { + pTemp = pDC->SelectObject(CBrush::FromHandle(_afxHatchBrush)); + if (pOldBrush == NULL) + pOldBrush = (CBrush*)pTemp; + pDC->SetBkMode(OPAQUE); + CRect rectTrue; + GetTrueRect(&rectTrue); + pDC->PatBlt(rectTrue.left, rectTrue.top, rectTrue.Width(), + rect.top-rectTrue.top, 0x000F0001 /* Pn */); + pDC->PatBlt(rectTrue.left, rect.bottom, + rectTrue.Width(), rectTrue.bottom-rect.bottom, 0x000F0001 /* Pn */); + pDC->PatBlt(rectTrue.left, rect.top, rect.left-rectTrue.left, + rect.Height(), 0x000F0001 /* Pn */); + pDC->PatBlt(rect.right, rect.top, rectTrue.right-rect.right, + rect.Height(), 0x000F0001 /* Pn */); + } + + // draw resize handles + if ((m_nStyle & (resizeInside|resizeOutside)) != 0) + { + UINT mask = GetHandleMask(); + for (int i = 0; i < 8; ++i) + { + if (mask & (1<FillSolidRect(rect, m_rectColor); + } + } + } + + // cleanup pDC state + if (pOldPen != NULL) + pDC->SelectObject(pOldPen); + if (pOldBrush != NULL) + pDC->SelectObject(pOldBrush); + VERIFY(pDC->RestoreDC(-1)); +} + +BOOL CMyTracker::SetCursor(CWnd* pWnd, UINT nHitTest) const +{ + // trackers should only be in client area + if (nHitTest != HTCLIENT) + return FALSE; + + // convert cursor position to client co-ordinates + CPoint point; + GetCursorPos(&point); + pWnd->ScreenToClient(&point); + + // do hittest and normalize hit + int nHandle = HitTestHandles(point); + if (nHandle < 0) + return FALSE; + + // need to normalize the hittest such that we get proper cursors + nHandle = NormalizeHit(nHandle); + + // handle special case of hitting area between handles + // (logically the same -- handled as a move -- but different cursor) + if (nHandle == hitMiddle && !m_rect.PtInRect(point)) + { + // only for trackers with hatchedBorder (ie. in-place resizing) + if (m_nStyle & hatchedBorder) + nHandle = (TrackerHit)9; + } + + //ASSERT(nHandle < _countof(_afxCursors)); + ::SetCursor(_afxCursors[nHandle]); + return TRUE; +} + +int CMyTracker::HitTest(CPoint point) const +{ + TrackerHit hitResult = hitNothing; + + CRect rectTrue; + GetTrueRect(&rectTrue); + ASSERT(rectTrue.left <= rectTrue.right); + ASSERT(rectTrue.top <= rectTrue.bottom); + if (rectTrue.PtInRect(point)) + { + if ((m_nStyle & (resizeInside|resizeOutside)) != 0) + hitResult = (TrackerHit)HitTestHandles(point); + else + hitResult = hitMiddle; + } + return hitResult; +} + +int CMyTracker::NormalizeHit(int nHandle) const +{ + ASSERT(nHandle <= 8 && nHandle >= -1); + if (nHandle == hitMiddle || nHandle == hitNothing) + return nHandle; + const AFX_HANDLEINFO* pHandleInfo = &_afxHandleInfo[nHandle]; + if (m_rect.Width() < 0) + { + nHandle = (TrackerHit)pHandleInfo->nInvertX; + pHandleInfo = &_afxHandleInfo[nHandle]; + } + if (m_rect.Height() < 0) + nHandle = (TrackerHit)pHandleInfo->nInvertY; + return nHandle; +} + +BOOL CMyTracker::Track(CWnd* pWnd, CPoint point, BOOL bAllowInvert, + CWnd* pWndClipTo) +{ + // perform hit testing on the handles + int nHandle = HitTestHandles(point); + if (nHandle < 0) + { + // didn't hit a handle, so just return FALSE + return FALSE; + } + + // otherwise, call helper function to do the tracking + m_bAllowInvert = bAllowInvert; + return TrackHandle(nHandle, pWnd, point, pWndClipTo); +} + +BOOL CMyTracker::TrackRubberBand(CWnd* pWnd, CPoint point, BOOL bAllowInvert) +{ + // simply call helper function to track from bottom right handle + m_bAllowInvert = bAllowInvert; + m_rect.SetRect(point.x, point.y, point.x, point.y); + return TrackHandle(hitBottomRight, pWnd, point, NULL); +} + +void CMyTracker::DrawTrackerRect( + LPCRECT lpRect, CWnd* pWndClipTo, CDC* pDC, CWnd* pWnd) +{ + // first, normalize the rectangle for drawing + + /*CRect rect = *lpRect; + rect.NormalizeRect(); + + // convert to client coordinates + if (pWndClipTo != NULL) + { + pWnd->ClientToScreen(&rect); + pWndClipTo->ScreenToClient(&rect); + } + + CSize size(0, 0); + if (!m_bFinalErase) + { + // otherwise, size depends on the style + if (m_nStyle & hatchedBorder) + { + size.cx = size.cy = max(1, GetHandleSize(rect)-1); + rect.InflateRect(size); + } + else + { + size.cx = CX_BORDER; + size.cy = CY_BORDER; + } + } + + // and draw it + if (m_bFinalErase || !m_bErase) + { + pDC->DrawDragRect(rect, size, m_rectLast, m_sizeLast); + } + + // remember last rectangles + m_rectLast = rect; + m_sizeLast = size; +*/ + //˺ǻСλʱ + //ڱҪ,ҪʹĻעʾȥ! + ((CCatchScreenDlg *)pWnd)->InvalidateRgnWindow(); + +} + +void CMyTracker::AdjustRect(int nHandle, LPRECT) +{ + if (nHandle == hitMiddle) + return; + + // convert the handle into locations within m_rect + int *px, *py; + GetModifyPointers(nHandle, &px, &py, NULL, NULL); + + // enforce minimum width + int nNewWidth = m_rect.Width(); + int nAbsWidth = m_bAllowInvert ? abs(nNewWidth) : nNewWidth; + if (px != NULL && nAbsWidth < m_sizeMin.cx) + { + nNewWidth = nAbsWidth != 0 ? nNewWidth / nAbsWidth : 1; + //ASSERT((int*)px - (int*)&m_rect < _countof(_afxRectInfo)); + const AFX_RECTINFO* pRectInfo = &_afxRectInfo[(int*)px - (int*)&m_rect]; + *px = *(int*)((BYTE*)&m_rect + pRectInfo->nOffsetAcross) + + nNewWidth * m_sizeMin.cx * -pRectInfo->nSignAcross; + } + + // enforce minimum height + int nNewHeight = m_rect.Height(); + int nAbsHeight = m_bAllowInvert ? abs(nNewHeight) : nNewHeight; + if (py != NULL && nAbsHeight < m_sizeMin.cy) + { + nNewHeight = nAbsHeight != 0 ? nNewHeight / nAbsHeight : 1; + //ASSERT((int*)py - (int*)&m_rect < _countof(_afxRectInfo)); + const AFX_RECTINFO* pRectInfo = &_afxRectInfo[(int*)py - (int*)&m_rect]; + *py = *(int*)((BYTE*)&m_rect + pRectInfo->nOffsetAcross) + + nNewHeight * m_sizeMin.cy * -pRectInfo->nSignAcross; + } +} + +void CMyTracker::GetTrueRect(LPRECT lpTrueRect) const +{ + ASSERT(AfxIsValidAddress(lpTrueRect, sizeof(RECT))); + + CRect rect = m_rect; + rect.NormalizeRect(); + int nInflateBy = 0; + if ((m_nStyle & (resizeOutside|hatchedBorder)) != 0) + nInflateBy += GetHandleSize() - 1; + if ((m_nStyle & (solidLine|dottedLine)) != 0) + ++nInflateBy; + rect.InflateRect(nInflateBy, nInflateBy); + *lpTrueRect = rect; +} + +void CMyTracker::OnChangedRect(const CRect& /*rectOld*/) +{ + // no default implementation, useful for derived classes +} + +///////////////////////////////////////////////////////////////////////////// +// CMyTracker implementation helpers + +void CMyTracker::GetHandleRect(int nHandle, CRect* pHandleRect) const +{ + ASSERT(nHandle < 8); + + // get normalized rectangle of the tracker + CRect rectT = m_rect; + rectT.NormalizeRect(); + if ((m_nStyle & (solidLine|dottedLine)) != 0) + rectT.InflateRect(+1, +1); + + // since the rectangle itself was normalized, we also have to invert the + // resize handles. + nHandle = NormalizeHit(nHandle); + + // handle case of resize handles outside the tracker + int size = GetHandleSize(); + + if(m_nStyle & resizeOutside) + { + if(1000000 & m_nStyle) + { + rectT.InflateRect(size-size/2-1, size-size/2-1); + } + else + { + rectT.InflateRect(size-1, size-1); + } + } + + // calculate position of the resize handle + int nWidth = rectT.Width(); + int nHeight = rectT.Height(); + CRect rect; + const AFX_HANDLEINFO* pHandleInfo = &_afxHandleInfo[nHandle]; + rect.left = *(int*)((BYTE*)&rectT + pHandleInfo->nOffsetX); + rect.top = *(int*)((BYTE*)&rectT + pHandleInfo->nOffsetY); + rect.left += size * pHandleInfo->nHandleX; + rect.top += size * pHandleInfo->nHandleY; + rect.left += pHandleInfo->nCenterX * (nWidth - size) / 2; + rect.top += pHandleInfo->nCenterY * (nHeight - size) / 2; + rect.right = rect.left + size; + rect.bottom = rect.top + size; + + *pHandleRect = rect; +} + +int CMyTracker::GetHandleSize(LPCRECT lpRect) const +{ + if (lpRect == NULL) + lpRect = &m_rect; + + int size = m_nHandleSize; + if (!(m_nStyle & resizeOutside)) + { + // make sure size is small enough for the size of the rect + int sizeMax = min(abs(lpRect->right - lpRect->left), + abs(lpRect->bottom - lpRect->top)); + if (size * 2 > sizeMax) + size = sizeMax / 2; + } + + return size; +} + +int CMyTracker::HitTestHandles(CPoint point) const +{ + CRect rect; + UINT mask = GetHandleMask(); + + // see if hit anywhere inside the tracker + GetTrueRect(&rect); + if (!rect.PtInRect(point)) + return hitNothing; // totally missed + + // see if we hit a handle + for (int i = 0; i < 8; ++i) + { + if (mask & (1<= 0); + ASSERT(nHandle <= 8); // handle 8 is inside the rect + + // don't handle if capture already set + if (::GetCapture() != NULL) + return FALSE; + + AfxLockTempMaps(); // protect maps while looping + + ASSERT(!m_bFinalErase); + + // save original width & height in pixels + int nWidth = m_rect.Width(); + int nHeight = m_rect.Height(); + + // set capture to the window which received this message + pWnd->SetCapture(); + ASSERT(pWnd == CWnd::GetCapture()); + pWnd->UpdateWindow(); + if (pWndClipTo != NULL) + pWndClipTo->UpdateWindow(); + CRect rectSave = m_rect; + + // find out what x/y coords we are supposed to modify + int *px, *py; + int xDiff, yDiff; + GetModifyPointers(nHandle, &px, &py, &xDiff, &yDiff); + xDiff = point.x - xDiff; + yDiff = point.y - yDiff; + + // get DC for drawing + CDC* pDrawDC; + if (pWndClipTo != NULL) + { + // clip to arbitrary window by using adjusted Window DC + pDrawDC = pWndClipTo->GetDCEx(NULL, DCX_CACHE); + } + else + { + // otherwise, just use normal DC + pDrawDC = pWnd->GetDC(); + } + ASSERT_VALID(pDrawDC); + + CRect rectOld; + BOOL bMoved = FALSE; + + // get messages until capture lost or cancelled/accepted + for (;;) + { + MSG msg; + VERIFY(::GetMessage(&msg, NULL, 0, 0)); + + if (CWnd::GetCapture() != pWnd) + break; + + //ӵ,Ϣ͸ + DispatchMessage(&msg); + + switch (msg.message) + { + // handle movement/accept messages + case WM_LBUTTONUP: + case WM_MOUSEMOVE: + rectOld = m_rect; + // handle resize cases (and part of move) + if (px != NULL) + *px = (int)(short)LOWORD(msg.lParam) - xDiff; + if (py != NULL) + *py = (int)(short)HIWORD(msg.lParam) - yDiff; + + // handle move case + if (nHandle == hitMiddle) + { + m_rect.right = m_rect.left + nWidth; + m_rect.bottom = m_rect.top + nHeight; + } + // allow caller to adjust the rectangle if necessary + AdjustRect(nHandle, &m_rect); + + // only redraw and callback if the rect actually changed! + m_bFinalErase = (msg.message == WM_LBUTTONUP); + if (!rectOld.EqualRect(&m_rect) || m_bFinalErase) + { + if (bMoved) + { + m_bErase = TRUE; + DrawTrackerRect(&rectOld, pWndClipTo, pDrawDC, pWnd); + } + OnChangedRect(rectOld); + if (msg.message != WM_LBUTTONUP) + { + bMoved = TRUE; + } + } + if (m_bFinalErase) + goto ExitLoop; + + if (!rectOld.EqualRect(&m_rect)) + { + m_bErase = FALSE; + DrawTrackerRect(&m_rect, pWndClipTo, pDrawDC, pWnd); + } + break; + + // handle cancel messages + case WM_KEYDOWN: + if (msg.wParam != VK_ESCAPE) + break; + case WM_RBUTTONDOWN: + if (bMoved) + { + m_bErase = m_bFinalErase = TRUE; + //DrawTrackerRect(&m_rect, pWndClipTo, pDrawDC, pWnd); + } + m_rect = rectSave; + goto ExitLoop; + + // just dispatch rest of the messages + default: + DispatchMessage(&msg); + break; + } + + + } + +ExitLoop: + if (pWndClipTo != NULL) + pWndClipTo->ReleaseDC(pDrawDC); + else + pWnd->ReleaseDC(pDrawDC); + ReleaseCapture(); + + AfxUnlockTempMaps(FALSE); + + // restore rect in case bMoved is still FALSE + if (!bMoved) + m_rect = rectSave; + m_bFinalErase = FALSE; + m_bErase = FALSE; + + // return TRUE only if rect has changed + return !rectSave.EqualRect(&m_rect); +} + +void CMyTracker::GetModifyPointers( + int nHandle, int** ppx, int** ppy, int* px, int* py) +{ + ASSERT(nHandle >= 0); + ASSERT(nHandle <= 8); + + if (nHandle == hitMiddle) + nHandle = hitTopLeft; // same as hitting top-left + + *ppx = NULL; + *ppy = NULL; + + // fill in the part of the rect that this handle modifies + // (Note: handles that map to themselves along a given axis when that + // axis is inverted don't modify the value on that axis) + + const AFX_HANDLEINFO* pHandleInfo = &_afxHandleInfo[nHandle]; + if (pHandleInfo->nInvertX != nHandle) + { + *ppx = (int*)((BYTE*)&m_rect + pHandleInfo->nOffsetX); + if (px != NULL) + *px = **ppx; + } + else + { + // middle handle on X axis + if (px != NULL) + *px = m_rect.left + abs(m_rect.Width()) / 2; + } + if (pHandleInfo->nInvertY != nHandle) + { + *ppy = (int*)((BYTE*)&m_rect + pHandleInfo->nOffsetY); + if (py != NULL) + *py = **ppy; + } + else + { + // middle handle on Y axis + if (py != NULL) + *py = m_rect.top + abs(m_rect.Height()) / 2; + } +} + +UINT CMyTracker::GetHandleMask() const +{ + UINT mask = 0x0F; // always have 4 corner handles + int size = m_nHandleSize*3; + if (abs(m_rect.Width()) - size > 4) + mask |= 0x50; + if (abs(m_rect.Height()) - size > 4) + mask |= 0xA0; + return mask; +} + + +////////////////////ӵĺ///////////////////////////////////////////////////////////// + +void CMyTracker::SetRectColor(COLORREF rectColor) +{ + m_rectColor=rectColor; + CreatePen(); + +} + +void CMyTracker::CreatePen() +{ + //if (_afxBlackDottedPen == NULL) + { + // create black dotted pen + _afxBlackDottedPen = ::CreatePen(PS_DOT, 0, m_rectColor); + if (_afxBlackDottedPen == NULL) + { + AfxUnlockGlobals(CRIT_RECTTRACKER); + AfxThrowResourceException(); + } + } + //if (_afxBlackSolidPen == NULL) + { + // create black dotted pen + _afxBlackSolidPen = ::CreatePen(PS_SOLID, 0, m_rectColor); + if (_afxBlackSolidPen == NULL) + { + AfxUnlockGlobals(CRIT_RECTTRACKER); + AfxThrowResourceException(); + } + } +} + +void CMyTracker::SetResizeCursor(UINT nID_N_S,UINT nID_W_E,UINT nID_NW_SE,UINT nID_NE_SW,UINT nIDMiddle) +{ +////////////////////////////////////////////////////////////////////////////////// +// N +// NW -----------|------------NE +// | | +// | | +// W | | E +// | Middle | +// | | +// | | +// SW-----------|------------SE +// S +//////////////////////////////////////////////////////////////////////////////////// + + _afxCursors[0] = AfxGetApp()->LoadCursor(nID_NW_SE); //nw + _afxCursors[1] = AfxGetApp()->LoadCursor(nID_NE_SW); //ne + _afxCursors[2] = _afxCursors[0]; //se + _afxCursors[3] = _afxCursors[1]; //sw + _afxCursors[4] = AfxGetApp()->LoadCursor(nID_N_S); //n + _afxCursors[5] = AfxGetApp()->LoadCursor(nID_W_E); //w + _afxCursors[6] = _afxCursors[4]; //s + _afxCursors[7] = _afxCursors[5]; //e + _afxCursors[8] = AfxGetApp()->LoadCursor(nIDMiddle); //m + // _afxCursors[9] = ::LoadCursor(hInst, MAKEINTRESOURCE(AFX_IDC_MOVE4WAY)); +} diff --git a/src/Screenshot/MyTracker.h b/src/Screenshot/MyTracker.h new file mode 100644 index 0000000..f1c4d61 --- /dev/null +++ b/src/Screenshot/MyTracker.h @@ -0,0 +1,102 @@ + +///////////////////////////////////////////////////////////////////////////// +// CMyTracker - simple rectangular tracking rectangle w/resize handles + +///////////////////////////////////////////////////////////////////////// +// Copy from MFC CRectTracker class +// Add Some member function +// Modify some place +//////////////////////////////////////////////////////////////////////// + +#define MYTRACKER_ + +#define CX_BORDER 1 +#define CY_BORDER 1 + +#define CRIT_RECTTRACKER 5 +void AFXAPI AfxLockGlobals(int nLockType); +void AFXAPI AfxUnlockGlobals(int nLockType); +void AFXAPI AfxDeleteObject(HGDIOBJ* pObject); + +class CMyTracker +{ +public: +// Constructors + CMyTracker(); + CMyTracker(LPCRECT lpSrcRect, UINT nStyle); + +// Style Flags + enum StyleFlags + { + solidLine = 1, dottedLine = 2, hatchedBorder = 4, + resizeInside = 8, resizeOutside = 16, hatchInside = 32, + resizeMiddle =80 //м + }; + +// Hit-Test codes + enum TrackerHit + { + hitNothing = -1, + hitTopLeft = 0, hitTopRight = 1, hitBottomRight = 2, hitBottomLeft = 3, + hitTop = 4, hitRight = 5, hitBottom = 6, hitLeft = 7, hitMiddle = 8 + }; + +// Attributes + UINT m_nStyle; // current state + CRect m_rect; // current position (always in pixels) + CSize m_sizeMin; // minimum X and Y size during track operation + int m_nHandleSize; // size of resize handles (default from WIN.INI) + +// Operations + void Draw(CDC* pDC) const; + void GetTrueRect(LPRECT lpTrueRect) const; + BOOL SetCursor(CWnd* pWnd, UINT nHitTest) const; + BOOL Track(CWnd* pWnd, CPoint point, BOOL bAllowInvert =TRUE, + CWnd* pWndClipTo = NULL); + BOOL TrackRubberBand(CWnd* pWnd, CPoint point, BOOL bAllowInvert = TRUE); + int HitTest(CPoint point) const; + int NormalizeHit(int nHandle) const; + +// Overridables + virtual void DrawTrackerRect(LPCRECT lpRect, CWnd* pWndClipTo, + CDC* pDC, CWnd* pWnd); + virtual void AdjustRect(int nHandle, LPRECT lpRect); + virtual void OnChangedRect(const CRect& rectOld); + virtual UINT GetHandleMask() const; + +// Implementation +public: + virtual ~CMyTracker(); + +public: + //*********************************************************** + //õ + void SetResizeCursor(UINT nID_N_S,UINT nID_W_E,UINT nID_NW_SE, + UINT nID_NE_SW,UINT nIDMiddle); + //ˢ,ڲ + void CreatePen(); + //þɫ + void SetRectColor(COLORREF rectColor); + + //************************************************************** + + //************************************************************** + //ǰɫ + COLORREF m_rectColor; + //************************************************************** + BOOL m_bAllowInvert; // flag passed to Track or TrackRubberBand + CRect m_rectLast; + CSize m_sizeLast; + BOOL m_bErase; // TRUE if DrawTrackerRect is called for erasing + BOOL m_bFinalErase; // TRUE if DragTrackerRect called for final erase + + // implementation helpers + int HitTestHandles(CPoint point) const; + void GetHandleRect(int nHandle, CRect* pHandleRect) const; + void GetModifyPointers(int nHandle, int**ppx, int**ppy, int* px, int*py); + virtual int GetHandleSize(LPCRECT lpRect = NULL) const; + BOOL TrackHandle(int nHandle, CWnd* pWnd, CPoint point, CWnd* pWndClipTo); + void Construct(); +}; + +//////////////////////////////////////// END OF FILE ///////////////////////////////////////////////////////// diff --git a/src/Screenshot/PopUpMenu.cpp b/src/Screenshot/PopUpMenu.cpp new file mode 100644 index 0000000..35e9b65 --- /dev/null +++ b/src/Screenshot/PopUpMenu.cpp @@ -0,0 +1,1466 @@ +/* +Copyright (C) 2004 Jacquelin POTIER +Dynamic aspect ratio code Copyright (C) 2004 Jacquelin POTIER + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +//----------------------------------------------------------------------------- +// Object: class helper for popupmenu control +//----------------------------------------------------------------------------- +#include "stdafx.h" +#include "popupmenu.h" +#define CPopUpMenu_ICON_SIZE_INCREMENT 2 // icon size increment used for shadow +#define CPopUpMenu_ICON_SHADOW_POSITION_DELTA 2 +#define CPopUpMenu_TRANSPARENCY_INCREASE 130 + +//----------------------------------------------------------------------------- +// Name: CPopUpMenu +// Object: Constructor. +// Parameters : +// in : +// out : +// return : +//----------------------------------------------------------------------------- +CPopUpMenu::CPopUpMenu() +{ + this->CommonConstructor(); + this->ParentPopUpMenu=NULL; +} +CPopUpMenu::CPopUpMenu(CPopUpMenu* ParentPopUpMenu) +{ + this->CommonConstructor(); + this->ParentPopUpMenu=ParentPopUpMenu; +} +//#include +//#pragma comment (lib,"uxtheme.lib") +void CPopUpMenu::CommonConstructor() +{ + this->bThemingEnabledForVistaOrNewer = FALSE; + if ( ((LOBYTE(LOWORD(::GetVersion())))>=6) ) // if vista or newer os + { + // dynamic loading to avoid static linking + HMODULE hmod = ::GetModuleHandle(_T("uxtheme.dll")); + if (!hmod) + hmod = ::LoadLibrary(_T("uxtheme.dll")); + if( hmod ) + { + FARPROC pfIsThemeActive = ::GetProcAddress(hmod,"IsThemeActive"); + this->bThemingEnabledForVistaOrNewer = pfIsThemeActive(); + } + + } + this->bAllowIconsEffects=TRUE; + this->MenuSelectCallback=NULL; + this->MenuSelectUserParam=NULL; + this->MouseRightButtonUpCallback=NULL; + this->MouseRightButtonUpUserParam=NULL; + + this->hPopUpMenu=::CreatePopupMenu(); + this->CurrentMenuId=0; + MENUINFO mnfo; + mnfo.cbSize = sizeof(mnfo); + mnfo.fMask = MIM_STYLE | MIM_MENUDATA; + mnfo.dwStyle = MNS_CHECKORBMP; //| MNS_AUTODISMISS can make menu to disappear when used on toolbar + mnfo.dwMenuData = (ULONG_PTR)this; + ::SetMenuInfo(this->hPopUpMenu, &mnfo); +} + +//----------------------------------------------------------------------------- +// Name: ~CPopUpMenu +// Object: Destructor. SUBMENU OBJECT ARE NOT DELETED +// Parameters : +// in : +// out : +// return : +//----------------------------------------------------------------------------- +CPopUpMenu::~CPopUpMenu() +{ + std::vector::iterator Iterator; + for (Iterator = this->ListLoadedBitmapToFree.begin(); Iterator!=this->ListLoadedBitmapToFree.end(); Iterator++) + { + ::DeleteObject(*Iterator); + } + ::DestroyMenu(this->hPopUpMenu); +} + +//----------------------------------------------------------------------------- +// Name: GetControlHandle +// Object: return the handle to the control +// Parameters : +// in : +// out : +// return : HWND handle to the control +//----------------------------------------------------------------------------- +HMENU CPopUpMenu::GetControlHandle() +{ + return this->hPopUpMenu; +} + +//----------------------------------------------------------------------------- +// Name: GetParentPopUpMenu +// Object: return pointer to the parent menu or NULL if no parent menu +// Parameters : +// in : +// out : +// return : pointer to the parent menu or NULL if no parent menu +//----------------------------------------------------------------------------- +CPopUpMenu* CPopUpMenu::GetParentPopUpMenu() +{ + return this->ParentPopUpMenu; +} + +//----------------------------------------------------------------------------- +// Name: GetNextMenuId +// Object: get next unique menu Id for all Menu and SubMenu +// Parameters : +// in : +// out : +// return : next unique menu Id for all Menu and SubMenu +//----------------------------------------------------------------------------- +UINT CPopUpMenu::GetNextMenuId() +{ + if (this->ParentPopUpMenu) + return this->ParentPopUpMenu->GetNextMenuId(); + else + { + // this assume we'll never return a 0 menuId + // (as 0 is returned by TrackPopupMenuEx if no item is selected) + this->CurrentMenuId++; + return this->CurrentMenuId; + } +} + +//----------------------------------------------------------------------------- +// Name: GetNextMenuId +// Object: get max used unique menu Id for all Menu and SubMenu +// Parameters : +// in : +// out : +// return : max used unique menu Id for all Menu and SubMenu +//----------------------------------------------------------------------------- +UINT CPopUpMenu::GetMaxMenuId() +{ + if (this->ParentPopUpMenu) + return this->ParentPopUpMenu->GetMaxMenuId(); + else + { + return this->CurrentMenuId; + } +} + +//----------------------------------------------------------------------------- +// Name: GetSubMenu +// Object: get sub menu associated menu id +// Parameters : +// in : UINT MenuID : menu id +// out : +// return : CPopUpMenu object pointer on success, NULL if no sub menu associated (or on error) +//----------------------------------------------------------------------------- +CPopUpMenu* CPopUpMenu::GetSubMenu(UINT MenuID) +{ + MENUITEMINFO mii={0}; + mii.cbSize=sizeof(MENUITEMINFO); + mii.fMask=MIIM_SUBMENU | MIIM_DATA; + if (!::GetMenuItemInfo(this->hPopUpMenu,MenuID,FALSE,&mii)) + return NULL; + if (!mii.hSubMenu) + return NULL; + + MENUINFO mi={0}; + mi.cbSize = sizeof(MENUINFO); + mi.fMask = MIM_MENUDATA; + if (!::GetMenuInfo(mii.hSubMenu,&mi)) + return NULL; + return (CPopUpMenu*)mi.dwMenuData; +} + +//----------------------------------------------------------------------------- +// Name: SetIcon +// Object: set menu item icon (loads default icon size) +// Parameters : +// in : UINT MenuID : menu id +// int IdIcon : resource icon id +// HINSTANCE hInstance : module handle containing icon id +// out : +// return : TRUE on success +//----------------------------------------------------------------------------- +BOOL CPopUpMenu::SetIcon(UINT MenuID,int IdIcon,HINSTANCE hInstance) +{ + return this->SetIcon(MenuID,IdIcon,hInstance,0,0); +} + +//----------------------------------------------------------------------------- +// Name: SetIcon +// Object: set menu item icon +// Parameters : +// in : UINT MenuID : menu id +// int IdIcon : resource icon id +// int Width : icon width +// int Height : icon height +// HINSTANCE hInstance : module handle containing icon id +// out : +// return : TRUE on success +//----------------------------------------------------------------------------- +BOOL CPopUpMenu::SetIcon(UINT MenuID,int IdIcon,HINSTANCE hInstance,int Width,int Height) +{ + return this->SetIcon(MenuID,(HICON)::LoadImage(hInstance, MAKEINTRESOURCE(IdIcon),IMAGE_ICON,Width,Height,LR_SHARED)); +} + +//----------------------------------------------------------------------------- +// Name: SetIcon +// Object: set menu item icon +// Parameters : +// in : UINT MenuID : menu id +// HICON hIcon : icon handle +// out : +// return : TRUE on success +//----------------------------------------------------------------------------- +BOOL CPopUpMenu::SetIcon(UINT MenuID,HICON hIcon) +{ + MENUITEMINFO mii={0}; + mii.cbSize=sizeof(MENUITEMINFO); + if (!hIcon) + return FALSE; + + this->SetMenuItemBitmapInfo(&mii,hIcon); + + return ::SetMenuItemInfo(this->hPopUpMenu,MenuID,FALSE,&mii); +} + +//----------------------------------------------------------------------------- +// Name: Add +// Object: +// Parameters : +// in : TCHAR* Name : name of menu +// out : +// return : Id of item menu (used to remove it),0 if failed +//----------------------------------------------------------------------------- +UINT CPopUpMenu::Add(TCHAR* Name) +{ + return this->Add(Name,NULL,this->GetItemCount()); +} + +//----------------------------------------------------------------------------- +// Name: Add +// Object: +// Parameters : +// in : TCHAR* Name : name of menu +// UINT Index : 0 based menu index +// out : +// return : Id of item menu (used to remove it),0 if failed +//----------------------------------------------------------------------------- +UINT CPopUpMenu::Add(TCHAR* Name,UINT Index) +{ + return this->Add(Name,NULL,Index); +} + +//----------------------------------------------------------------------------- +// Name: Add +// Object: +// Parameters : +// in : TCHAR* Name : name of menu +// HICON hIcon : icon handle +// out : +// return : Id of item menu (used to remove it),0 if failed +//----------------------------------------------------------------------------- +UINT CPopUpMenu::Add(TCHAR* Name,HICON hIcon) +{ + return this->Add(Name,hIcon,this->GetItemCount()); +} + +//----------------------------------------------------------------------------- +// Name: Add +// Object: +// Parameters : +// in : TCHAR* Name : name of menu +// int IdIcon : icon id +// HINSTANCE hInstance : hinstance containing icon id +// out : +// return : Id of item menu (used to remove it),0 if failed +//----------------------------------------------------------------------------- +UINT CPopUpMenu::Add(TCHAR* Name,int IdIcon,HINSTANCE hInstance) +{ + // load icon + HICON hIcon=(HICON)::LoadImage(hInstance, MAKEINTRESOURCE(IdIcon),IMAGE_ICON,0,0,LR_SHARED); + return this->Add(Name,hIcon,this->GetItemCount()); +} + +//----------------------------------------------------------------------------- +// Name: Add +// Object: +// Parameters : +// in : TCHAR* Name : name of menu +// int IdIcon : icon id +// HINSTANCE hInstance : hinstance containing icon id +// UINT Index : 0 based menu index +// out : +// return : Id of item menu (used to remove it),0 if failed +//----------------------------------------------------------------------------- +UINT CPopUpMenu::Add(TCHAR* Name,int IdIcon,HINSTANCE hInstance,UINT Index) +{ + return this->Add(Name,IdIcon,hInstance,0,0,Index); +} +//----------------------------------------------------------------------------- +// Name: Add +// Object: +// Parameters : +// in : TCHAR* Name : name of menu +// int IdIcon : icon id +// HINSTANCE hInstance : hinstance containing icon id +// int Width : icon width +// int Height : icon height +// UINT Index : 0 based menu index +// out : +// return : Id of item menu (used to remove it),0 if failed +//----------------------------------------------------------------------------- +UINT CPopUpMenu::Add(TCHAR* Name,int IdIcon,HINSTANCE hInstance,int Width,int Height,UINT Index) +{ + // load icon + HICON hIcon=(HICON)::LoadImage(hInstance, MAKEINTRESOURCE(IdIcon),IMAGE_ICON,Width,Height,LR_SHARED); + return this->Add(Name,hIcon,Index); +} + +//----------------------------------------------------------------------------- +// Name: Add +// Object: +// Parameters : +// in : TCHAR* Name : name of menu +// HICON hIcon : icon handle +// UINT Index : 0 based menu index +// out : +// return : Id of item menu (used to remove it),0 if failed +//----------------------------------------------------------------------------- +UINT CPopUpMenu::Add(TCHAR* Name,HICON hIcon,UINT Index) +{ + UINT MenuId=this->GetNextMenuId(); + + MENUITEMINFO mii={0}; + mii.cbSize=sizeof(MENUITEMINFO); + mii.fMask = MIIM_FTYPE|MIIM_STRING|MIIM_ID; + mii.fType = MFT_STRING; + mii.dwTypeData=Name; + mii.wID=MenuId; + + this->SetMenuItemBitmapInfo(&mii,hIcon); + + // insert menu + if (!::InsertMenuItem(this->hPopUpMenu, + Index, + TRUE, + &mii + ) + ) + return 0; + + return MenuId; +} + +//----------------------------------------------------------------------------- +// Name: ReplaceMenuId +// Object: change menu id. +// WARNING NO CHECK IS DONE IF NEW ID IS ALREADY EXISTING : if it's the case +// you will run into trouble for the multiple id access +// +// Parameters : +// in : UINT OldMenuID : old menu id +// UINT NewMenuID : new menu id +// out : +// return : TRUE on success +//----------------------------------------------------------------------------- +BOOL CPopUpMenu::ReplaceMenuId(UINT OldMenuID,UINT NewMenuID) +{ + MENUITEMINFO mii={0}; + mii.cbSize=sizeof(MENUITEMINFO); + mii.fMask=MIIM_ID; + mii.wID=NewMenuID; + return ::SetMenuItemInfo(this->hPopUpMenu,OldMenuID,FALSE,&mii); +} + +//----------------------------------------------------------------------------- +// Name: SetCheckedState +// Object: +// Parameters : +// in : UINT MenuID : menu id +// BOOL bChecked : new checked state +// out : +// return : +//----------------------------------------------------------------------------- +void CPopUpMenu::SetCheckedState(UINT MenuID,BOOL bChecked) +{ + UINT uCheck; + if(bChecked) + uCheck=MF_CHECKED; + else + uCheck=MF_UNCHECKED; + ::CheckMenuItem(this->hPopUpMenu,MenuID,MF_BYCOMMAND|uCheck); +} + +//----------------------------------------------------------------------------- +// Name: IsChecked +// Object: +// Parameters : +// in : UINT MenuID : menu id +// out : +// return : TRUE if menu item is checked +//----------------------------------------------------------------------------- +BOOL CPopUpMenu::IsChecked(UINT MenuID) +{ + if (MF_CHECKED & ::GetMenuState(this->hPopUpMenu,MenuID,MF_BYCOMMAND)) + return TRUE; + else + return FALSE; +} + +//----------------------------------------------------------------------------- +// Name: SetEnabledState +// Object: +// Parameters : +// in : UINT MenuID : menu id +// BOOL bEnabled : new enabled state +// out : +// return : +//----------------------------------------------------------------------------- +void CPopUpMenu::SetEnabledState(UINT MenuID,BOOL bEnabled) +{ + UINT uEnable; + if(bEnabled) + uEnable=MF_ENABLED; + else + uEnable=MF_GRAYED; + ::EnableMenuItem(this->hPopUpMenu,MenuID,MF_BYCOMMAND|uEnable); +} + +//----------------------------------------------------------------------------- +// Name: IsEnabled +// Object: +// Parameters : +// in : UINT MenuID : menu id +// out : +// return : +//----------------------------------------------------------------------------- +BOOL CPopUpMenu::IsEnabled(UINT MenuID) +{ + UINT uEnable=::GetMenuState(this->hPopUpMenu,MenuID,MF_BYCOMMAND); + if (uEnable==(UINT)-1) + return FALSE; + + return !(uEnable & (MF_DISABLED|MF_GRAYED)); +} + + +//----------------------------------------------------------------------------- +// Name: Remove +// Object: +// Parameters : +// in : UINT MenuID +// out : +// return : +//----------------------------------------------------------------------------- +void CPopUpMenu::Remove(UINT MenuID) +{ + ::RemoveMenu(this->hPopUpMenu,MenuID,MF_BYCOMMAND); +} + +//----------------------------------------------------------------------------- +// Name: AddSeparator +// Object: +// Parameters : +// in : +// out : +// return : Id of item menu (used to remove it),0 if failed +//----------------------------------------------------------------------------- +UINT CPopUpMenu::AddSeparator() +{ + UINT MenuId=this->GetNextMenuId(); + if(!::AppendMenu( this->hPopUpMenu,MF_SEPARATOR,MenuId,_T(""))) + return 0; + return MenuId; +} + +//----------------------------------------------------------------------------- +// Name: AddSeparator +// Object: +// Parameters : +// in : UINT Index : menu index +// out : +// return : Id of item menu (used to remove it),0 if failed +//----------------------------------------------------------------------------- +UINT CPopUpMenu::AddSeparator(UINT Index) +{ + UINT MenuId=this->GetNextMenuId(); + if (!::InsertMenu( this->hPopUpMenu,Index, MF_SEPARATOR|MF_BYPOSITION,MenuId,_T(""))) + return 0; + return MenuId; +} + +//----------------------------------------------------------------------------- +// Name: AddSubMenu +// Object: +// Parameters : +// in : TCHAR* SubMenuName : Name of submenu +// CPopUpMenu* SubMenu : pointer to an initialized CPopUpMenu +// UINT Index : SubMenu 0 based index in the current menu +// out : +// return : Id of item menu (used to remove it),0 if failed +//----------------------------------------------------------------------------- +UINT CPopUpMenu::AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu) +{ + return this->AddSubMenu(SubMenuName,SubMenu,(UINT)-1); +} + +//----------------------------------------------------------------------------- +// Name: AddSubMenu +// Object: +// Parameters : +// in : TCHAR* SubMenuName : Name of submenu +// CPopUpMenu* SubMenu : pointer to an initialized CPopUpMenu +// UINT Index : SubMenu 0 based index in the current menu +// out : +// return : Id of item menu (used to remove it),0 if failed +//----------------------------------------------------------------------------- +UINT CPopUpMenu::AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu,UINT Index) +{ + return this->AddSubMenu(SubMenuName,SubMenu,0,Index); +} + +//----------------------------------------------------------------------------- +// Name: AddSubMenu +// Object: add submenu with icon +// Parameters : +// in : TCHAR* SubMenuName : Name of submenu +// CPopUpMenu* SubMenu : pointer to an initialized CPopUpMenu +// int IdIcon : icon id +// HINSTANCE hInstance : instance containing icon id +// UINT Index : SubMenu 0 based index in the current menu +// out : +// return : Id of item menu (used to remove it),0 if failed +//----------------------------------------------------------------------------- +UINT CPopUpMenu::AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu,int IdIcon,HINSTANCE hInstance) +{ + return this->AddSubMenu(SubMenuName,SubMenu,IdIcon,hInstance,(UINT)-1); +} + +//----------------------------------------------------------------------------- +// Name: AddSubMenu +// Object: add submenu with icon +// Parameters : +// in : TCHAR* SubMenuName : Name of submenu +// CPopUpMenu* SubMenu : pointer to an initialized CPopUpMenu +// int IdIcon : icon id +// HINSTANCE hInstance : instance containing icon id +// UINT Index : SubMenu 0 based index in the current menu +// out : +// return : Id of item menu (used to remove it),0 if failed +//----------------------------------------------------------------------------- +UINT CPopUpMenu::AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu,int IdIcon,HINSTANCE hInstance,UINT Index) +{ + HICON hIcon=(HICON)::LoadImage(hInstance, MAKEINTRESOURCE(IdIcon),IMAGE_ICON,0,0,LR_SHARED); + return this->AddSubMenu(SubMenuName,SubMenu,hIcon,Index); +} + +//----------------------------------------------------------------------------- +// Name: AddSubMenu +// Object: add submenu with icon +// Parameters : +// in : TCHAR* SubMenuName : Name of submenu +// CPopUpMenu* SubMenu : pointer to an initialized CPopUpMenu +// HICON hIcon : submenu icon handle +// out : +// return : Id of item menu (used to remove it),0 if failed +//----------------------------------------------------------------------------- +UINT CPopUpMenu::AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu,HICON hIcon) +{ + return this->AddSubMenu(SubMenuName,SubMenu,hIcon,(UINT)-1); +} + +//----------------------------------------------------------------------------- +// Name: AddSubMenu +// Object: add submenu with icon +// Parameters : +// in : TCHAR* SubMenuName : Name of submenu +// CPopUpMenu* SubMenu : pointer to an initialized CPopUpMenu +// HICON hIcon : submenu icon handle +// UINT Index : SubMenu 0 based index in the current menu +// out : +// return : Id of item menu (used to remove it),0 if failed +//----------------------------------------------------------------------------- +UINT CPopUpMenu::AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu,HICON hIcon,UINT Index) +{ + MENUITEMINFO MenuItem={0}; + UINT MenuId=this->GetNextMenuId(); + + MenuItem.cbSize=sizeof(MENUITEMINFO); + MenuItem.fMask=MIIM_SUBMENU|MIIM_STRING|MIIM_ID; + MenuItem.hSubMenu=SubMenu->GetControlHandle(); + MenuItem.fType=MFT_STRING; + MenuItem.cch=(UINT)_tcslen(SubMenuName); + MenuItem.dwTypeData=SubMenuName; + MenuItem.wID=MenuId; + + this->SetMenuItemBitmapInfo(&MenuItem,hIcon); + + if(!::InsertMenuItem(this->hPopUpMenu,Index,TRUE,&MenuItem)) + return 0; + return MenuId; +} + +void CPopUpMenu::SetMenuItemBitmapInfo(MENUITEMINFO* pMenuItem,HICON hIcon) +{ + if (hIcon) + { + // on vista or newer os, if theming is enabled selected icon is not color-inverted, + // so there's no need to draw icon by ourselves, let system do it + if (this->bThemingEnabledForVistaOrNewer) + { + SIZE IconSize; + ICONINFO IconInfo; + if (::GetIconInfo(hIcon,&IconInfo)) + { + IconSize.cx = IconInfo.xHotspot*2; + IconSize.cy = IconInfo.yHotspot*2; + + // free icon infos + ::DeleteObject(IconInfo.hbmColor); + ::DeleteObject(IconInfo.hbmMask); + } + else + { + IconSize.cx = ::GetSystemMetrics(SM_CXICON); + IconSize.cy = ::GetSystemMetrics(SM_CYICON); + } + + + BITMAPV5HEADER bi; + void *lpBits; + + ZeroMemory(&bi,sizeof(BITMAPV5HEADER)); + bi.bV5Size = sizeof(BITMAPV5HEADER); + bi.bV5Width = IconSize.cx; + bi.bV5Height = IconSize.cy; + bi.bV5Planes = 1; + bi.bV5BitCount = 32; + bi.bV5Compression = BI_BITFIELDS; + // The following mask specification specifies a supported 32 BPP + // alpha format for Windows XP. + bi.bV5RedMask = 0x00FF0000; + bi.bV5GreenMask = 0x0000FF00; + bi.bV5BlueMask = 0x000000FF; + bi.bV5AlphaMask = 0xFF000000; + + HDC hdcScreen = ::GetDC(NULL); + HDC hMemDC = ::CreateCompatibleDC(hdcScreen); + HBITMAP hBitmap = ::CreateDIBSection(hdcScreen, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD)0); + // HBITMAP hBitmap = ::CreateCompatibleBitmap(hMemDC, IconSize.cx, IconSize.cy); + HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemDC, hBitmap); + HBRUSH hBackgroundBrush = ::CreateSolidBrush(::GetSysColor(COLOR_MENU)); + //::DrawIcon(hMemDC, 0, 0, hIcon); + ::DrawIconEx(hMemDC,0,0,hIcon,IconSize.cx,IconSize.cy,0, + /*0*/ hBackgroundBrush, /* some icons needs a background color*/ + DI_NORMAL /*| DI_NOMIRROR*/ ); + + ::SelectObject(hMemDC, hOldBitmap); + ::DeleteObject(hBackgroundBrush); + ::DeleteDC(hMemDC); + ::ReleaseDC(NULL,hdcScreen); + + pMenuItem->fMask|=MIIM_BITMAP; + pMenuItem->hbmpItem = hBitmap; + ListLoadedBitmapToFree.push_back(hBitmap); +// to do : MenuItem.hbmpItem with must be deleted + } + else + { + // before vista icon of selected item in menu was inverted by default. + // to avoid this we have to manually draw icon by oursleves inside callback + + // set item data for WM_MEASUREITEM and WM_DRAWITEM messages + pMenuItem->fMask|=MIIM_DATA; + pMenuItem->dwItemData=(ULONG_PTR)hIcon; + + // set owner drawn for icon drawing + pMenuItem->fMask|=MIIM_BITMAP; + pMenuItem->hbmpItem = HBMMENU_CALLBACK; + + //// for full owner drawn type use + //pMenuItem->fType|= MFT_OWNERDRAW; + } + } +} + +//----------------------------------------------------------------------------- +// Name: GetItemCount +// Object: +// Parameters : +// in : +// out : +// return : number of item in the menu +//----------------------------------------------------------------------------- +int CPopUpMenu::GetItemCount() +{ + return ::GetMenuItemCount(this->hPopUpMenu); +} + +//----------------------------------------------------------------------------- +// Name: GetText +// Object: +// Parameters : +// in : UINT MenuID : menu ID +// int pszTextMaxSize : pszText max size in TCHAR. If 0, GetItemCount returns the +// number of required TCHAR +// out : TCHAR* pszText : Pointer to the buffer that receives the null-terminated string +// return : If the function succeeds, the return value specifies the number of characters copied to the buffer, +// not including the terminating null character +// If the function fails, the return value is zero +//----------------------------------------------------------------------------- +int CPopUpMenu::GetText(UINT MenuID,OUT TCHAR* pszText,IN int pszTextMaxSize) +{ + return ::GetMenuString(this->hPopUpMenu,MenuID,pszText,pszTextMaxSize,MF_BYCOMMAND); +} + +//----------------------------------------------------------------------------- +// Name: SetText +// Object: +// Parameters : +// in : UINT MenuID : menu ID +// TCHAR* pszText : Pointer to the input buffer +// out : +// return : TRUE on success, FALSE on error +//----------------------------------------------------------------------------- +BOOL CPopUpMenu::SetText(UINT MenuID,TCHAR* pszText) +{ + MENUITEMINFO MenuItemInfo={0}; + MenuItemInfo.cbSize=sizeof(MENUITEMINFO); + MenuItemInfo.fMask=MIIM_STRING; + MenuItemInfo.fType=MFT_STRING; + MenuItemInfo.cch=(UINT)_tcslen(pszText); + MenuItemInfo.dwTypeData=pszText; + + return ::SetMenuItemInfo(this->hPopUpMenu,MenuID,FALSE,&MenuItemInfo); +} + +//----------------------------------------------------------------------------- +// Name: GetID +// Object: retrieve menu ID from menu index +// Parameters : +// in : UINT Menu index : index +// out : +// return : -1 if not found, else menu id +//----------------------------------------------------------------------------- +int CPopUpMenu::GetID(UINT MenuIndex) +{ + MENUITEMINFO MenuItemInfo={0}; + MenuItemInfo.cbSize=sizeof(MENUITEMINFO); + MenuItemInfo.fMask=MIIM_ID; + if (!::GetMenuItemInfo(this->hPopUpMenu,MenuIndex,TRUE,&MenuItemInfo)) + return -1; + return (int)MenuItemInfo.wID; + // return GetMenuItemID(this->hPopUpMenu,MenuIndex); +} + +//----------------------------------------------------------------------------- +// Name: GetIndex +// Object: retrieve menu index from menu ID +// Parameters : +// in : UINT MenuId : menu id +// out : +// return : -1 if not found, else menu index +//----------------------------------------------------------------------------- +int CPopUpMenu::GetIndex(UINT MenuId) +{ + int Cnt; + for (Cnt=0;CntGetItemCount();Cnt++) + { + if ((UINT)this->GetID(Cnt)==MenuId) + { + return Cnt; + } + } + return -1; +} + +//----------------------------------------------------------------------------- +// Name: Show +// Object: +// Parameters : +// in : int x : Horizontal location of the shortcut menu, in screen coordinates +// int y : Vertical location of the shortcut menu, in screen coordinates +// HWND hOwner : owner control handle +// out : +// return : 0 if no item selected, item id else +//----------------------------------------------------------------------------- +UINT CPopUpMenu::Show(int x,int y, HWND hOwner) +{ + return this->Show(x,y,hOwner,FALSE); +} +//----------------------------------------------------------------------------- +// Name: Show +// Object: +// Parameters : +// in : int x : Horizontal location of the shortcut menu, in screen coordinates +// int y : Vertical location of the shortcut menu, in screen coordinates +// HWND hOwner : owner control handle +// BOOL PositionRelativeToOwner : TRUE if position is relative to owner +// FALSE for an absolute position +// out : +// return : 0 if no item selected, item id else +//----------------------------------------------------------------------------- +UINT CPopUpMenu::Show(int x,int y, HWND hOwner,BOOL PositionRelativeToOwner) +{ + return this->Show(x,y,hOwner,PositionRelativeToOwner,FALSE); +} + +//----------------------------------------------------------------------------- +// Name: Show +// Object: +// Parameters : +// in : int x : Horizontal location of the shortcut menu, in screen coordinates +// int y : Vertical location of the shortcut menu, in screen coordinates +// HWND hOwner : owner control handle +// BOOL PositionRelativeToOwner : TRUE if position is relative to owner +// FALSE for an absolute position +// BOOL ShowUpper : TRUE to show menu upper y point +// out : +// return : 0 if no item selected, item id else +//----------------------------------------------------------------------------- +UINT CPopUpMenu::Show(int x,int y, HWND hOwner,BOOL PositionRelativeToOwner,BOOL ShowUpper) +{ + if (PositionRelativeToOwner) + { + RECT Rect; + ::GetWindowRect(hOwner,&Rect); + x+=Rect.left; + y+=Rect.top; + } + // menu flag must be without TPM_RIGHTBUTTON flag to get WM_MENURBUTTONUP messages + UINT fuFlags=TPM_LEFTALIGN|TPM_RETURNCMD; + if (ShowUpper) + { + fuFlags|=TPM_BOTTOMALIGN; + } + else + { + fuFlags|=TPM_TOPALIGN; + } + + UINT TrackPopupMenuRet; + HWND hWnd=hOwner; + + + + // install a subclassing wndproc + UINT_PTR uIdSubclass=0; + DWORD_PTR dwRefData=(DWORD_PTR)this; + ::SetWindowSubclass(hWnd,CPopUpMenu::SubClassWndProc,uIdSubclass,dwRefData); + + ::SetForegroundWindow(hWnd); // in case of use with notify icons + TrackPopupMenuRet=(UINT)::TrackPopupMenuEx(this->hPopUpMenu,fuFlags,x,y,hOwner,NULL); + + if (TrackPopupMenuRet==0) + { + if (::GetLastError()==ERROR_POPUP_ALREADY_ACTIVE) + TrackPopupMenuRet=(UINT)::TrackPopupMenuEx(this->hPopUpMenu,fuFlags|TPM_RECURSE,x,y,hOwner,NULL); + } + + // remove subclassing wndproc + ::RemoveWindowSubclass(hWnd,CPopUpMenu::SubClassWndProc,uIdSubclass); + + + // MSDN : + //However, when the current window is the foreground window, + //the second time this menu is displayed, it displays and then immediately disappears. + //To correct this, you must force a task switch to the application that called + //TrackPopupMenu at some time in the near future. + //This is done by posting a benign message to the window or thread + ::PostMessage(hWnd, WM_NULL, 0, 0); + + return TrackPopupMenuRet; +} + +//----------------------------------------------------------------------------- +// Name: OnMeasureItem +// Object: return needed pRect size to display picture (full item menu for MFT_OWNERDRAW) +// Parameters : +// in : HWND hwnd : hwnd +// inout : LPMEASUREITEMSTRUCT lpmis : pointer measured item struct +// out : +// return : TRUE if message has been proceed +//----------------------------------------------------------------------------- +BOOL CPopUpMenu::OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis) +{ + UNREFERENCED_PARAMETER(hwnd); + + // assume type is a menu + if (lpmis->CtlType!=ODT_MENU) + return FALSE; + + // assume to have item associated data + if (!lpmis->itemData) + return FALSE; + + // extract icon infos from item data + ICONINFO IconInfo; + if (!::GetIconInfo((HICON)lpmis->itemData, &IconInfo)) + return FALSE; + + // get bitmap from icon + BITMAP Bitmap; + ::GetObject(IconInfo.hbmColor, sizeof(Bitmap), &Bitmap); + + // free icon infos + ::DeleteObject(IconInfo.hbmColor); + ::DeleteObject(IconInfo.hbmMask); + + // use bitmap size infos + lpmis->itemWidth = Bitmap.bmWidth; + lpmis->itemHeight = Bitmap.bmHeight; + + if (this->bAllowIconsEffects) + { + lpmis->itemWidth+= CPopUpMenu_ICON_SIZE_INCREMENT; + lpmis->itemHeight+= CPopUpMenu_ICON_SIZE_INCREMENT; + } + + return TRUE; +} + + + +HICON CreateGrayscaleIcon(HICON hIcon) +{ + HICON hGrayIcon = NULL; + HDC hdc = NULL, hMemDC1 = NULL, hMemDC2 = NULL; + HBITMAP hOldBmp1 = NULL, hOldBmp2 = NULL; + ICONINFO csII, csGrayII; + BOOL bRetValue = FALSE; + + bRetValue = ::GetIconInfo(hIcon, &csII); + if (bRetValue == FALSE) + return NULL; + + hdc = ::GetDC(NULL); + if (!hdc) + return NULL; + + hMemDC1 = ::CreateCompatibleDC(hdc); + if (!hMemDC1) + { + ::ReleaseDC(NULL, hdc); + return NULL; + } + + hMemDC2 = ::CreateCompatibleDC(hdc); + if (!hMemDC2) + { + ::DeleteDC(hMemDC1); + ::ReleaseDC(NULL, hdc); + return NULL; + } + + + BITMAPV5HEADER bi; + DWORD Width; + DWORD Height; + void *lpBits; + + Width = csII.xHotspot*2; // width of Icon + Height = csII.yHotspot*2; // height of Icon + + ZeroMemory(&bi,sizeof(BITMAPV5HEADER)); + bi.bV5Size = sizeof(BITMAPV5HEADER); + bi.bV5Width = Width; + bi.bV5Height = Height; + bi.bV5Planes = 1; + bi.bV5BitCount = 32; + bi.bV5Compression = BI_BITFIELDS; + // The following mask specification specifies a supported 32 BPP + // alpha format for Windows XP. + bi.bV5RedMask = 0x00FF0000; + bi.bV5GreenMask = 0x0000FF00; + bi.bV5BlueMask = 0x000000FF; + bi.bV5AlphaMask = 0xFF000000; + + // Create the DIB section with an alpha channel. + csGrayII.hbmColor = ::CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD)0); + + if (csGrayII.hbmColor) + { + hOldBmp1 = (HBITMAP)::SelectObject(hMemDC1, csII.hbmColor); + hOldBmp2 = (HBITMAP)::SelectObject(hMemDC2, csGrayII.hbmColor); + + ::BitBlt(hMemDC2, 0, 0, Width, Height, hMemDC1, 0, 0, SRCCOPY); + + DWORD dwLoopY = 0, dwLoopX = 0; + COLORREF crPixel = 0; + BYTE byNewPixel = 0; + DWORD *lpdwPixel; + lpdwPixel = (DWORD *)lpBits; + + for (dwLoopY = 0; dwLoopY < Height; dwLoopY++) + { + for (dwLoopX = 0; dwLoopX < Width; dwLoopX++) + { + crPixel = (*lpdwPixel) & 0x00FFFFFF; + + if (crPixel) + byNewPixel = (BYTE)((GetRValue(crPixel) * 0.299) + (GetGValue(crPixel) * 0.587) + (GetBValue(crPixel) * 0.114)); + else + byNewPixel = 0; + + // Clear the color bits + *lpdwPixel &= 0xFF000000; + // Set the new alpha bits + *lpdwPixel |= RGB(byNewPixel, byNewPixel, byNewPixel) ; + + lpdwPixel++; + } // for + } // for + + ::SelectObject(hMemDC1, hOldBmp1); + ::SelectObject(hMemDC2, hOldBmp2); + + csGrayII.hbmMask = csII.hbmMask; + + csGrayII.fIcon = TRUE; + hGrayIcon = ::CreateIconIndirect(&csGrayII); + ::DeleteObject(csGrayII.hbmColor); + } // if + + ::DeleteObject(csII.hbmColor); + ::DeleteObject(csII.hbmMask); + ::DeleteDC(hMemDC1); + ::DeleteDC(hMemDC2); + ::ReleaseDC(NULL, hdc); + + return hGrayIcon; +} // End of CreateGrayscaleIcon + + +HICON CreateAlphaIcon(HICON hIcon,int AlphaChange,HBRUSH BackgroundBrush) +{ + HDC hMemDC; + DWORD Width, Height; + BITMAPV5HEADER bi; + HBITMAP hBitmap, hOldBitmap; + void *lpBits; + DWORD x,y; + HICON hNewIcon = NULL; + + ICONINFO OriginalIconInfos; + if(!::GetIconInfo(hIcon,&OriginalIconInfos)) + return NULL; + + ICONINFO ii; + ii.fIcon = TRUE; // Change fIcon to TRUE to create an alpha icon + ii.xHotspot = 0; + ii.yHotspot = 0; + + if (!AlphaChange) + { + ii.hbmMask = OriginalIconInfos.hbmMask; + ii.hbmColor = OriginalIconInfos.hbmColor; + + // Create the alpha cursor with the alpha DIB section. + hNewIcon = ::CreateIconIndirect(&ii); + + ::DeleteObject(OriginalIconInfos.hbmColor); + ::DeleteObject(OriginalIconInfos.hbmMask); + + return hNewIcon; + } + + Width = OriginalIconInfos.xHotspot*2; // width of Icon + Height = OriginalIconInfos.yHotspot*2; // height of Icon + + ZeroMemory(&bi,sizeof(BITMAPV5HEADER)); + bi.bV5Size = sizeof(BITMAPV5HEADER); + bi.bV5Width = Width; + bi.bV5Height = Height; + bi.bV5Planes = 1; + bi.bV5BitCount = 32; + bi.bV5Compression = BI_BITFIELDS; + // The following mask specification specifies a supported 32 BPP + // alpha format for Windows XP. + bi.bV5RedMask = 0x00FF0000; + bi.bV5GreenMask = 0x0000FF00; + bi.bV5BlueMask = 0x000000FF; + bi.bV5AlphaMask = 0xFF000000; + + HDC hdc; + hdc = ::GetDC(NULL); + + // Create the DIB section with an alpha channel. + hBitmap = ::CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD)0); + hMemDC = ::CreateCompatibleDC(hdc); + + // select bitmap + hOldBitmap = (HBITMAP)::SelectObject(hMemDC, hBitmap); + + // Draw something on the DIB section. + ::DrawIconEx(hMemDC,0,0,hIcon,Width,Height,0, + /*0*/ BackgroundBrush, /* some icons needs a background color*/ + DI_NORMAL); + + // Create an empty mask bitmap. + HBITMAP hMonoBitmap = ::CreateBitmap(Width,Height,1,1,NULL); + + DWORD *lpdwPixel; + lpdwPixel = (DWORD *)lpBits; + + BYTE bAlpha; + for (x=0;x> 24); + + if (AlphaChange<0) + { + if (!bAlpha) + bAlpha = 0xFF; + // increase transparency + bAlpha = (BYTE)__max(bAlpha+AlphaChange,1); // 0 : no transparency + } + else + { + // reduce transparency only for not fully transparent bytes + if (bAlpha) + { + bAlpha = (BYTE)__min(bAlpha+AlphaChange,0xff); + } + } + + // Clear the alpha bits + *lpdwPixel &= 0x00FFFFFF; + // Set the new alpha bits + *lpdwPixel |= ( bAlpha <<24) ; + + lpdwPixel++; + } + } + + ii.hbmMask = hMonoBitmap; + ii.hbmColor = hBitmap; + + // Create the alpha cursor with the alpha DIB section. + hNewIcon = ::CreateIconIndirect(&ii); + + ::SelectObject(hMemDC, hOldBitmap); + ::DeleteDC(hMemDC); + + ::DeleteObject(hBitmap); + ::DeleteObject(hMonoBitmap); + + ::DeleteObject(OriginalIconInfos.hbmColor); + ::DeleteObject(OriginalIconInfos.hbmMask); + + ::ReleaseDC(NULL,hdc); + + return hNewIcon; +} + +//----------------------------------------------------------------------------- +// Name: CreateAlphaOrGreyscaleIcon +// Object: This function creates an alpha modified or a greyscale icon starting from a given icon. +// The resulting icon will have the same size of the original one. +// Notice the return icon handle must be free by calling ::DeleteObject +// Parameters : +// in : HWND hwnd : hwnd +// int Alpha [-255;255] negative value to increase alpha transparency +// BOOL bGreyscale TRUE to convert to greyscale +// out : +// return : NULL on error hIcon on success +//----------------------------------------------------------------------------- +HICON CreateAlphaOrGreyscaleIcon(HICON hIcon,BOOL bGreyIcon,int AlphaChange,HBRUSH BackgroundBrush) +{ + HICON hGreyIcon = hIcon; + HICON hNewIcon; + + if (bGreyIcon) + hGreyIcon = CreateGrayscaleIcon(hIcon); + + hNewIcon = CreateAlphaIcon(hGreyIcon,AlphaChange,BackgroundBrush); + + if (bGreyIcon) + ::DestroyIcon(hGreyIcon); + + return hNewIcon; +} + + +//----------------------------------------------------------------------------- +// Name: OnDrawItem +// Object: do picture rendering (full item rendering if MFT_OWNERDRAW) +// Parameters : +// in : HWND hwnd : hwnd +// LPDRAWITEMSTRUCT lpdis : pointer display item info struct +// out : +// return : TRUE if message has been proceed +//----------------------------------------------------------------------------- +BOOL CPopUpMenu::OnDrawItem(HWND hwnd, LPDRAWITEMSTRUCT lpdis) +{ + UNREFERENCED_PARAMETER(hwnd); + + // assume type is a menu + if (lpdis->CtlType!=ODT_MENU) + return FALSE; + + // assume handle match our menu or sub menu + if (this->hPopUpMenu!=(HMENU)lpdis->hwndItem) + { + if (!this->IsSubMenu(this->hPopUpMenu,(HMENU)lpdis->hwndItem)) + return FALSE; + } + + // assume to have item associated data + if (!lpdis->itemData) + return FALSE; + + ICONINFO IconInfo; + // extract icon infos from item data + if (!::GetIconInfo((HICON)lpdis->itemData, &IconInfo)) + return FALSE; + + UINT Width = IconInfo.xHotspot*2; + UINT Height = IconInfo.yHotspot*2; + + // free icon infos + ::DeleteObject(IconInfo.hbmColor); + ::DeleteObject(IconInfo.hbmMask); + + //// render bitmap + //::DrawIconEx(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,(HICON) lpdis->itemData, Bitmap.bmWidth, Bitmap.bmHeight, 0, NULL, DI_NORMAL); + + BOOL bSelected = ( (lpdis->itemState & ODS_SELECTED) == ODS_SELECTED); + BOOL bDisabled = ( (lpdis->itemState & ODS_DISABLED) == ODS_DISABLED); + BOOL bChecked = ( (lpdis->itemState & ODS_CHECKED) == ODS_CHECKED); + //HBITMAP hBmp = LoadBitmap (NULL, MAKEINTRESOURCE(OBM_CHECK)); + // bChecked is always FALSE, else we have to play with MFT_OWNERDRAW + + HBRUSH CurrentBrush = NULL; + UINT Delta=0; + + if (this->bAllowIconsEffects) + Delta =( (bSelected && !bDisabled) ? (CPopUpMenu_ICON_SIZE_INCREMENT-CPopUpMenu_ICON_SHADOW_POSITION_DELTA)/2 : CPopUpMenu_ICON_SIZE_INCREMENT/2 ); + + // if item is disabled, draw only grey scale icon + if ( bDisabled ) + { + HICON hGreyIcon=CreateGrayscaleIcon((HICON) lpdis->itemData); + ::DrawIconEx(lpdis->hDC, lpdis->rcItem.left+Delta, lpdis->rcItem.top+Delta,hGreyIcon, Width, Height, 0, NULL, DI_NORMAL); + ::DestroyIcon(hGreyIcon); + return TRUE; + } + + if (this->bAllowIconsEffects) + { + // if item is checked, draw rectangle around icon + if (bChecked) + { + // get system colors + COLORREF CheckedColor; + COLORREF MenuHilightColor = ::GetSysColor(COLOR_MENUHILIGHT); + COLORREF MenuColor = ::GetSysColor(COLOR_MENU); + + // get luminosity difference + int LuminosityDelta = // grey highlighted menu color - grey menu color + (int)((GetRValue(MenuHilightColor) * 0.299) + (GetGValue(MenuHilightColor) * 0.587) + (GetBValue(MenuHilightColor) * 0.114)) + - (int)((GetRValue(MenuColor) * 0.299) + (GetGValue(MenuColor) * 0.587) + (GetBValue(MenuColor) * 0.114)); + LuminosityDelta/=2; + + // forge checked color + CheckedColor = RGB( + __max( __min( GetRValue(MenuHilightColor) - LuminosityDelta , 255 ) , 0 ), + __max( __min( GetGValue(MenuHilightColor) - LuminosityDelta , 255 ) , 0 ), + __max( __min( GetBValue(MenuHilightColor) - LuminosityDelta , 255 ) , 0 ) + ); + + // create pen and select it + HPEN hPen = ::CreatePen(PS_SOLID, 1, (bSelected ? ::GetSysColor(COLOR_MENU) : ::GetSysColor(COLOR_MENUHILIGHT))); + HPEN OldPen= (HPEN)::SelectObject(lpdis->hDC,hPen); + // create brush and select it + CurrentBrush = ::CreateSolidBrush(CheckedColor); + HBRUSH OldBrush = (HBRUSH)::SelectObject(lpdis->hDC,CurrentBrush); + + // draw rectangle around icon with selected pen and brush + ::Rectangle(lpdis->hDC, lpdis->rcItem.left,lpdis->rcItem.top,lpdis->rcItem.right,lpdis->rcItem.bottom); + + // select original brush and pen + ::SelectObject(lpdis->hDC,OldBrush); + ::SelectObject(lpdis->hDC,OldPen); + } + else + { + if ( bSelected ) + CurrentBrush = ::CreateSolidBrush(::GetSysColor(COLOR_MENUHILIGHT)); + else + CurrentBrush = ::CreateSolidBrush(::GetSysColor(COLOR_MENU)); + } + + if ( bSelected ) + { + UINT DeltaShadow=(CPopUpMenu_ICON_SIZE_INCREMENT+CPopUpMenu_ICON_SHADOW_POSITION_DELTA)/2; + HICON hAlphaIcon=CreateAlphaOrGreyscaleIcon((HICON) lpdis->itemData,TRUE,-CPopUpMenu_TRANSPARENCY_INCREASE,CurrentBrush); + ::DrawIconEx(lpdis->hDC, lpdis->rcItem.left+DeltaShadow, lpdis->rcItem.top+DeltaShadow,hAlphaIcon, Width, Height, 0, NULL, DI_NORMAL); + ::DestroyIcon(hAlphaIcon); + } + } + + // render bitmap + // ::DrawState(lpdis->hDC, (HBRUSH)NULL, NULL,(LPARAM)(HICON)lpdis->itemData, 0, lpdis->rcItem.left+Delta, lpdis->rcItem.top+Delta, Bitmap.bmWidth, Bitmap.bmHeight, DSS_NORMAL | DST_ICON); + ::DrawIconEx(lpdis->hDC, lpdis->rcItem.left+Delta, lpdis->rcItem.top+Delta,(HICON) lpdis->itemData, Width, Height, 0, NULL, DI_NORMAL); + + if (CurrentBrush) + ::DeleteObject(CurrentBrush); + + return TRUE; +} + +//----------------------------------------------------------------------------- +// Name: IsSubMenu +// Object: check if hSubMenu is a submenu of hMenu +// Parameters : +// in : HMENU hMenu : a menu handle +// HMENU hSubMenu : sub menu handle to check +// out : +// return : TRUE hMenu is a submenu of current menu +//----------------------------------------------------------------------------- +BOOL CPopUpMenu::IsSubMenu(HMENU hMenu,HMENU hSubMenu) +{ + int NbItems=::GetMenuItemCount(hMenu); + + MENUITEMINFO mii; + mii.cbSize=sizeof(MENUITEMINFO); + mii.fMask=MIIM_SUBMENU; + for (int Cnt=0;CntIsSubMenu(mii.hSubMenu,hSubMenu)) + return TRUE; + + } + + return FALSE; +} + +//----------------------------------------------------------------------------- +// Name: SetMouseRightButtonUpCallback +// Object: set callback for WM_MENURBUTTONUP message +// Parameters : +// in : +// out : +// return : TRUE on success +//----------------------------------------------------------------------------- +BOOL CPopUpMenu::SetMouseRightButtonUpCallback(pfMessageCallback Callback,PVOID UserParam) +{ + // check callback validity + if (::IsBadCodePtr((FARPROC)Callback)) + return FALSE; + + this->MouseRightButtonUpCallback=Callback; + this->MouseRightButtonUpUserParam=UserParam; + + return TRUE; +} + +//----------------------------------------------------------------------------- +// Name: SetMenuSelectCallback +// Object: set callback for WM_MENUSELECT message +// Parameters : +// in : +// out : +// return : TRUE on success +//----------------------------------------------------------------------------- +BOOL CPopUpMenu::SetMenuSelectCallback(pfMessageCallback Callback,PVOID UserParam) +{ + // check callback validity + if (::IsBadCodePtr((FARPROC)Callback)) + return FALSE; + + this->MenuSelectCallback=Callback; + this->MenuSelectUserParam=UserParam; + + return TRUE; +} + +//----------------------------------------------------------------------------- +// Name: OnMouseRightButtonUp +// Object: called on WM_MENURBUTTONUP message, call callback if any +// Parameters : +// in : +// out : +// return : +//----------------------------------------------------------------------------- +void CPopUpMenu::OnMouseRightButtonUp(WPARAM wParam, LPARAM lParam) +{ + if (this->MouseRightButtonUpCallback) + this->MouseRightButtonUpCallback(wParam,lParam,this->MouseRightButtonUpUserParam); +} + +//----------------------------------------------------------------------------- +// Name: OnMenuSelect +// Object: called on WM_MENUSELECT message, call callback if any +// Parameters : +// in : +// out : +// return : +//----------------------------------------------------------------------------- +void CPopUpMenu::OnMenuSelect(WPARAM wParam, LPARAM lParam) +{ + if (this->MenuSelectCallback) + this->MenuSelectCallback(wParam,lParam,this->MenuSelectUserParam); +} + +//----------------------------------------------------------------------------- +// Name: SubClassWndProc +// Object: subclassing window proc +// Parameters : +// in : WndProc param +// out : +// return : +//----------------------------------------------------------------------------- +LRESULT CALLBACK CPopUpMenu::SubClassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,UINT_PTR uIdSubclass,DWORD_PTR dwRefData) +{ + UNREFERENCED_PARAMETER(uIdSubclass); + CPopUpMenu* pPopUpMenu=(CPopUpMenu*)dwRefData; + if (!pPopUpMenu) + return ::DefSubclassProc(hWnd,uMsg,wParam,lParam); + + switch (uMsg) + { + case WM_MEASUREITEM: + return pPopUpMenu->OnMeasureItem(hWnd, (LPMEASUREITEMSTRUCT) lParam); + + case WM_DRAWITEM: + return pPopUpMenu->OnDrawItem(hWnd, (LPDRAWITEMSTRUCT) lParam); + + case WM_MENURBUTTONUP: + // FIXME : WM_MENURBUTTONUP is not send for sub menus when they are expanded + pPopUpMenu->OnMouseRightButtonUp(wParam,lParam); + break; + case WM_MENUSELECT: + pPopUpMenu->OnMenuSelect(wParam,lParam); + break; + } + + return ::DefSubclassProc(hWnd,uMsg,wParam,lParam); +} \ No newline at end of file diff --git a/src/Screenshot/PopUpMenu.h b/src/Screenshot/PopUpMenu.h new file mode 100644 index 0000000..767190f --- /dev/null +++ b/src/Screenshot/PopUpMenu.h @@ -0,0 +1,117 @@ +/* +Copyright (C) 2004 Jacquelin POTIER +Dynamic aspect ratio code Copyright (C) 2004 Jacquelin POTIER + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +//----------------------------------------------------------------------------- +// Object: class helper for popupmenu control +//----------------------------------------------------------------------------- + +#pragma once +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 // for xp os +#endif +#include +#pragma warning (push) +#pragma warning(disable : 4005)// for '_stprintf' : macro redefinition in tchar.h +#include +#pragma warning (pop) +#include + +#include +#pragma comment (lib,"comctl32.lib") + +class CPopUpMenu +{ +public: + typedef void (*pfMessageCallback)(WPARAM wParam, LPARAM lParam,PVOID UserParam); + CPopUpMenu(); + CPopUpMenu(CPopUpMenu* ParentPopUpMenu); + ~CPopUpMenu(); + + HMENU GetControlHandle(); + CPopUpMenu* GetParentPopUpMenu(); + + UINT Add(TCHAR* Name); + UINT Add(TCHAR* Name,UINT Index); + UINT Add(TCHAR* Name,HICON hIcon); + UINT Add(TCHAR* Name,HICON hIcon,UINT Index); + UINT Add(TCHAR* Name,int IdIcon,HINSTANCE hInstance); + UINT Add(TCHAR* Name,int IdIcon,HINSTANCE hInstance,UINT Index); + UINT Add(TCHAR* Name,int IdIcon,HINSTANCE hInstance,int Width,int Height,UINT Index); + + UINT AddSeparator(); + UINT AddSeparator(UINT Index); + + UINT AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu,UINT Index); + UINT AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu); + UINT AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu,int IdIcon,HINSTANCE hInstance,UINT Index); + UINT AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu,int IdIcon,HINSTANCE hInstance); + UINT AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu,HICON hIcon,UINT Index); + UINT AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu,HICON hIcon); + + void SetCheckedState(UINT MenuID,BOOL bChecked); + BOOL IsChecked(UINT MenuID); + void SetEnabledState(UINT MenuID,BOOL bEnabled); + BOOL IsEnabled(UINT MenuID); + BOOL SetText(UINT MenuID,TCHAR* pszText); + BOOL SetIcon(UINT MenuID,int IdIcon,HINSTANCE hInstance); + BOOL SetIcon(UINT MenuID,int IdIcon,HINSTANCE hInstance,int Width,int Height); + BOOL SetIcon(UINT MenuID,HICON hIcon); + int GetText(UINT MenuID,TCHAR* pszText,int pszTextMaxSize); + CPopUpMenu* GetSubMenu(UINT MenuID); + + void Remove(UINT MenuID); + + int GetItemCount(); + int GetID(UINT MenuIndex); + int GetIndex(UINT MenuId); + + UINT Show(int x,int y, HWND hOwner); + UINT Show(int x,int y, HWND hOwner,BOOL PositionRelativeToOwner); + UINT Show(int x,int y, HWND hOwner,BOOL PositionRelativeToOwner,BOOL ShowUpper); + + UINT GetNextMenuId(); + UINT GetMaxMenuId(); + BOOL ReplaceMenuId(UINT OldMenuID,UINT NewMenuID); + + BOOL SetMouseRightButtonUpCallback(pfMessageCallback Callback,PVOID UserParam); + BOOL SetMenuSelectCallback(pfMessageCallback Callback,PVOID UserParam); + + BOOL bAllowIconsEffects; +private: + CPopUpMenu* ParentPopUpMenu; + HMENU hPopUpMenu; + int CurrentMenuId; + BOOL bThemingEnabledForVistaOrNewer; + std::vector ListLoadedBitmapToFree; + + pfMessageCallback MouseRightButtonUpCallback; + PVOID MouseRightButtonUpUserParam; + pfMessageCallback MenuSelectCallback; + PVOID MenuSelectUserParam; + + void CommonConstructor(); + void SetMenuItemBitmapInfo(MENUITEMINFO* pMenuItem,HICON hIcon); + BOOL IsSubMenu(HMENU hMenu,HMENU hSubMenu); + BOOL OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis); + BOOL OnDrawItem(HWND hwnd, LPDRAWITEMSTRUCT lpdis); + void OnMouseRightButtonUp(WPARAM wParam, LPARAM lParam); + void OnMenuSelect(WPARAM wParam, LPARAM lParam); + void FreeItemMemory(UINT MenuID); + void FreeItemBitmap(UINT MenuID); + static LRESULT CALLBACK SubClassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,UINT_PTR uIdSubclass,DWORD_PTR dwRefData); +}; diff --git a/src/Screenshot/ReadMe.txt b/src/Screenshot/ReadMe.txt new file mode 100644 index 0000000..f9da258 --- /dev/null +++ b/src/Screenshot/ReadMe.txt @@ -0,0 +1,73 @@ +================================================================================ +MICROSOFT : Screenshot Ŀ +=============================================================================== + +ӦóΪ Screenshot Ӧó򡣴Ӧó򲻽ʾ Microsoft Ļʹ÷ΪдӦó㡣 + +ļҪ Screenshot Ӧóÿļݡ + +Screenshot.vcproj +ʹӦóɵ VC++ ĿĿļ +ɸļ Visual C++ İ汾ϢԼйʹӦóѡƽ̨úĿܵϢ + +Screenshot.h +ӦóҪͷļĿضͷļ( Resource.h) CScreenshotApp Ӧóࡣ + +Screenshot.cpp +ǰӦó CScreenshotApp ҪӦóԴļ + +Screenshot.rc +dzʹõ Microsoft Windows Դб RES Ŀ¼д洢ͼꡢλͼ͹ꡣļֱ Microsoft Visual C++ нб༭ĿԴλ 2052 С + +res\Screenshot.ico +ӦóͼͼļͼҪԴļ Screenshot.rc С + +res\Screenshot.rc2 +ļ Microsoft Visual C++ нб༭ԴӦýԴ༭༭ԴڴļС + + +///////////////////////////////////////////////////////////////////////////// + +Ӧó򵼴һԻ: + +ScreenshotDlg.hScreenshotDlg.cpp - Ի +Щļ CScreenshotDlg ࡣඨӦóԻΪöԻģλ Screenshot.rc Уļ Microsoft Visual C++ нб༭ + + +///////////////////////////////////////////////////////////////////////////// + +: + +ActiveX ؼ +Ӧóʹ ActiveX ؼ֧֡ + +ӡӡԤ֧ +Ӧóͨ MFC CView еijԱڴӡӡúʹӡԤĴ롣 + +///////////////////////////////////////////////////////////////////////////// + +׼ļ: + +StdAfx.hStdAfx.cpp +ЩļΪ Screenshot.pch Ԥͷ (PCH) ļΪ StdAfx.obj Ԥļ + +Resource.h +DZ׼ͷļµԴ ID +Microsoft Visual C++ ȡ´ļ + +Screenshot.manifest + Ӧó嵥ļ Windows XP Ӧó + ض汾г򼯵ԡسʹô + Ϣӳ򼯻ʵij򼯻 + Ӧó˽ϢӦó嵥Ϊ·ַΪ + Ӧóִļװͬļеⲿ .manifest ļ + ҲԴʽڸÿִļС +///////////////////////////////////////////////////////////////////////////// + +ע: + +ӦóʹáTODO:ָʾӦӻԶԴ벿֡ + +Ӧóڹ DLL ʹ MFCҪ·Щ MFC DLLӦóõϵͳĵǰòͬҪ·ӦıػԴ MFC90XXX.DLLйĸϢμ MSDN ĵй Redistributing Visual C++ applications (· Visual C++ Ӧó)½ڡ + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Screenshot/Screenshot.aps b/src/Screenshot/Screenshot.aps new file mode 100644 index 0000000..59ef8ce Binary files /dev/null and b/src/Screenshot/Screenshot.aps differ diff --git a/src/Screenshot/Screenshot.cpp b/src/Screenshot/Screenshot.cpp new file mode 100644 index 0000000..e7b1caf --- /dev/null +++ b/src/Screenshot/Screenshot.cpp @@ -0,0 +1,174 @@ +// Screenshot.cpp : ӦóΪ +// + +#include "stdafx.h" +#include "Screenshot.h" +#include "ScreenshotDlg.h" +#include "CatchScreenDlg.h" +#include + + +using namespace Gdiplus; +#pragma comment(lib,"GdiPlus.lib") + + + + + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + +#define SHIFTED 0x8000 + + +// CScreenshotApp + +BEGIN_MESSAGE_MAP(CScreenshotApp, CWinApp) + ON_COMMAND(ID_HELP, &CWinApp::OnHelp) +END_MESSAGE_MAP() + + +// CScreenshotApp + +CScreenshotApp::CScreenshotApp() +{ + // TODO: ڴ˴ӹ룬 + // Ҫijʼ InitInstance + +} + + +// Ψһһ CScreenshotApp + +CScreenshotApp theApp; + + +// CScreenshotApp ʼ + +BOOL CScreenshotApp::InitInstance() +{ + // һ Windows XP ϵӦó嵥ָҪ + // ʹ ComCtl32.dll 汾 6 ߰汾ÿӻʽ + //Ҫ InitCommonControlsEx()򣬽޷ڡ + INITCOMMONCONTROLSEX InitCtrls; + InitCtrls.dwSize = sizeof(InitCtrls); + // ΪҪӦóʹõ + // ؼࡣ + InitCtrls.dwICC = ICC_WIN95_CLASSES; + InitCommonControlsEx(&InitCtrls); + + CWinApp::InitInstance(); + + GdiplusStartupInput input; + GdiplusStartup(&m_gdiplusToken,&input,NULL); + + AfxEnableControlContainer(); + + // ׼ʼ + // δʹЩܲϣС + // տִļĴСӦƳ + // Ҫضʼ + // ڴ洢õע + // TODO: Ӧʵ޸ĸַ + // ޸Ϊ˾֯ + SetRegistryKey(_T("ӦóɵıӦó")); + + CScreenshotDlg dlg; + m_pMainWnd = &dlg; + INT_PTR nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + // TODO: ڴ˷ôʱ + // ȷرնԻĴ + } + else if (nResponse == IDCANCEL) + { + // TODO: ڴ˷ôʱ + // ȡرնԻĴ + } + + // ڶԻѹرգԽ FALSE Ա˳Ӧó + // ӦóϢá + return FALSE; +} + +BOOL CScreenshotApp::ProcessMessageFilter(int code, LPMSG lpMsg) +{ + if(m_hwndDlg != NULL) + { + // ϢǴӶԻ򷢳Ļӿؼ,ͽд + if((lpMsg->hwnd == m_hwndDlg) || ::IsChild(m_hwndDlg, lpMsg->hwnd)) + { + // ϢWM_KEYDOWN,÷λ + if(lpMsg->message == WM_KEYDOWN) + { + CRect rect(0,0,0,0); + CCatchScreenDlg * pDlg=(CCatchScreenDlg *)AfxGetMainWnd(); + + rect = pDlg->m_rectTracker.m_rect; + + if(pDlg->m_bFirstDraw) + { + //ShiftС + BOOL bIsShiftDown = FALSE; + + if (GetKeyState(VK_SHIFT) & SHIFTED) + bIsShiftDown = TRUE; + + //////////////////////////////////////////////////// + + switch(lpMsg->wParam) + { + case VK_UP: + + //Shift,ֻһ + if(!bIsShiftDown) + rect.top-=1; + + rect.bottom-=1; + pDlg->m_rectTracker.m_rect = rect; + pDlg->InvalidateRgnWindow(); + break; + + case VK_DOWN: + rect.top+=1; + if(!bIsShiftDown) + rect.bottom+=1; + + pDlg->m_rectTracker.m_rect=rect; + pDlg->InvalidateRgnWindow(); + break; + + case VK_LEFT: + if(!bIsShiftDown) + rect.left-=1; + rect.right-=1; + + pDlg->m_rectTracker.m_rect=rect; + pDlg->InvalidateRgnWindow(); + break; + + case VK_RIGHT: + rect.left+=1; + if(!bIsShiftDown) + rect.right+=1; + + pDlg->m_rectTracker.m_rect=rect; + pDlg->InvalidateRgnWindow(); + break; + } + } + } + + } + } + + return CWinApp::ProcessMessageFilter(code, lpMsg); +} +int CScreenshotApp::ExitInstance() +{ + GdiplusShutdown(m_gdiplusToken); + + return CWinApp::ExitInstance(); +} diff --git a/src/Screenshot/Screenshot.h b/src/Screenshot/Screenshot.h new file mode 100644 index 0000000..5a0dfb6 --- /dev/null +++ b/src/Screenshot/Screenshot.h @@ -0,0 +1,38 @@ +// Screenshot.h : PROJECT_NAME Ӧóͷļ +// + +#pragma once + +#ifndef __AFXWIN_H__ + #error "ڰļ֮ǰstdafx.h PCH ļ" +#endif + +#include "resource.h" // + +// CScreenshotApp: +// йشʵ֣ Screenshot.cpp +// + +class CScreenshotApp : public CWinApp +{ +public: + CScreenshotApp(); + +// д + public: + virtual BOOL InitInstance(); + + + HWND m_hwndDlg; + virtual BOOL ProcessMessageFilter(int code, LPMSG lpMsg); + +// ʵ + + DECLARE_MESSAGE_MAP() +private: + ULONG_PTR m_gdiplusToken; +public: + virtual int ExitInstance(); +}; + +extern CScreenshotApp theApp; \ No newline at end of file diff --git a/src/Screenshot/Screenshot.rc b/src/Screenshot/Screenshot.rc new file mode 100644 index 0000000..888cd37 --- /dev/null +++ b/src/Screenshot/Screenshot.rc @@ -0,0 +1,217 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#ifndef APSTUDIO_INVOKED +#include "targetver.h" +#endif +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Chinese (P.R.C.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) +#ifdef _WIN32 +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED +#pragma code_page(936) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#ifndef APSTUDIO_INVOKED\r\n" + "#include ""targetver.h""\r\n" + "#endif\r\n" + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)\r\n" + "LANGUAGE 4, 2\r\n" + "#pragma code_page(936)\r\n" + "#include ""res\\Screenshot.rc2"" // Microsoft Visual C++ ༭Դ\r\n" + "#include ""l.CHS\\afxres.rc"" // ׼\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON "res\\Screenshot.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_SCREENSHOT_DIALOG DIALOGEX 0, 0, 181, 59 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_APPWINDOW +CAPTION "Screenshot" +FONT 9, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + PUSHBUTTON "ͼ",IDC_BTN_START,65,22,50,14 +END + +IDD_DIALOGFORIMG DIALOGEX 0, 0, 169, 140 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP +EXSTYLE WS_EX_TRANSPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + EDITTEXT IDC_EDIT1,14,20,137,93,ES_MULTILINE | ES_READONLY | NOT WS_BORDER +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080403a8" + BEGIN + VALUE "CompanyName", "TODO: <˾>" + VALUE "FileDescription", "TODO: <ļ˵>" + VALUE "FileVersion", "1.0.0.1" + VALUE "InternalName", "Screenshot.exe" + VALUE "LegalCopyright", "TODO: (C) <˾>Ȩ" + VALUE "OriginalFilename", "Screenshot.exe" + VALUE "ProductName", "TODO: <Ʒ>" + VALUE "ProductVersion", "1.0.0.1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x804, 936 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_SCREENSHOT_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 174 + TOPMARGIN, 7 + BOTTOMMARGIN, 52 + END + + IDD_DIALOGFORIMG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 162 + TOPMARGIN, 7 + BOTTOMMARGIN, 133 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_BITMAP_BK BITMAP "res\\brackground.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// PNG +// + +IDB_ARROW PNG "res\\Arrow.png" +IDB_RECTANGLE PNG "res\\Rectangle.png" +IDB_CIRCLE PNG "res\\Circle.png" +IDB_BRUSH PNG "res\\Brush.PNG" +IDB_MOSAIC PNG "res\\Mosaic.png" +IDB_TEXT PNG "res\\Text.png" +IDB_UNDO PNG "res\\Undo.png" +IDB_SAVE PNG "res\\Save.png" +IDB_EXIT PNG "res\\Exit.png" +IDB_FINISH PNG "res\\Finish.png" + +///////////////////////////////////////////////////////////////////////////// +// +// Cursor +// + +IDC_CURSOR1 CURSOR "res\\arrow_m.cur" +#endif // Chinese (P.R.C.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) +LANGUAGE 4, 2 +#pragma code_page(936) +#include "res\Screenshot.rc2" // Microsoft Visual C++ ༭Դ +#include "l.CHS\afxres.rc" // ׼ +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Screenshot/Screenshot.vcproj b/src/Screenshot/Screenshot.vcproj new file mode 100644 index 0000000..35207b4 --- /dev/null +++ b/src/Screenshot/Screenshot.vcproj @@ -0,0 +1,368 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Screenshot/Screenshot.vcxproj b/src/Screenshot/Screenshot.vcxproj new file mode 100644 index 0000000..1e2906e --- /dev/null +++ b/src/Screenshot/Screenshot.vcxproj @@ -0,0 +1,169 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {24E39ACB-AB81-485D-8D36-749B3F5EC1E8} + Screenshot + MFCProj + + + + Application + v120_xp + Dynamic + Unicode + true + + + Application + v120_xp + Dynamic + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>15.0.27924.0 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + + + + _DEBUG;%(PreprocessorDefinitions) + false + true + + + Disabled + WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Use + Level3 + EditAndContinue + + + _DEBUG;%(PreprocessorDefinitions) + 0x0804 + $(IntDir);%(AdditionalIncludeDirectories) + + + true + Windows + MachineX86 + + + + + NDEBUG;%(PreprocessorDefinitions) + false + true + + + MaxSpeed + true + WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions) + false + MultiThreadedDLL + true + Use + Level3 + ProgramDatabase + + + NDEBUG;%(PreprocessorDefinitions) + 0x0804 + $(IntDir);%(AdditionalIncludeDirectories) + + + true + Windows + true + true + MachineX86 + + + + + + + + + + + + Create + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Screenshot/ScreenshotDlg.cpp b/src/Screenshot/ScreenshotDlg.cpp new file mode 100644 index 0000000..9f9b47a --- /dev/null +++ b/src/Screenshot/ScreenshotDlg.cpp @@ -0,0 +1,116 @@ +// ScreenshotDlg.cpp : ʵļ +// + +#include "stdafx.h" +#include "Screenshot.h" +#include "ScreenshotDlg.h" + +#include "CatchScreenDlg.h" + + +#ifdef _DEBUG +//#define new DEBUG_NEW +#endif + + +// CScreenshotDlg Ի + + +CScreenshotDlg::CScreenshotDlg(CWnd* pParent /*=NULL*/) + : CDialog(CScreenshotDlg::IDD, pParent) +{ + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +void CScreenshotDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); +} + +BEGIN_MESSAGE_MAP(CScreenshotDlg, CDialog) + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + //}}AFX_MSG_MAP + ON_BN_CLICKED(IDC_BTN_START, &CScreenshotDlg::OnBnClickedBtnStart) + ON_WM_CTLCOLOR() + ON_WM_MOUSEMOVE() +END_MESSAGE_MAP() + + +// CScreenshotDlg Ϣ + +BOOL CScreenshotDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // ô˶ԻͼꡣӦóڲǶԻʱܽԶ + // ִд˲ + SetIcon(m_hIcon, TRUE); // ôͼ + SetIcon(m_hIcon, FALSE); // Сͼ + + // TODO: ڴӶijʼ + + // ʹ + ::SetWindowPos(GetSafeHwnd(), HWND_TOPMOST, 150, 150, 0, 0, + SWP_NOMOVE|SWP_NOSIZE|SWP_NOREDRAW); + + return TRUE; // ǽõؼ򷵻 TRUE +} + +// ԻСťҪĴ +// Ƹͼꡣʹĵ/ͼģ͵ MFC Ӧó +// ⽫ɿԶɡ + +void CScreenshotDlg::OnPaint() +{ + if (IsIconic()) + { + CPaintDC dc(this); // ڻƵ豸 + + SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); + + // ʹͼڹо + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // ͼ + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CDialog::OnPaint(); + } +} + +//û϶Сʱϵͳô˺ȡù +//ʾ +HCURSOR CScreenshotDlg::OnQueryDragIcon() +{ + return static_cast(m_hIcon); +} + +//---------------------------------------------------------------------- +// ̺߳,ͼ +// +UINT SccreenShot_Thread (LPVOID lpParam) +{ + HWND hWndMain = (HWND) lpParam; + CCatchScreenDlg dlg; + dlg.DoModal(); + + ::ShowWindow(hWndMain,SW_SHOW); + return 0; +} + +void CScreenshotDlg::OnBnClickedBtnStart() +{ + ::ShowWindow (m_hWnd, SW_HIDE); + //ʹñڳǰ + ::AfxBeginThread (SccreenShot_Thread, (LPVOID)GetSafeHwnd()); + //::ShowWindow (GetSafeHwnd(), SW_SHOW); +} + diff --git a/src/Screenshot/ScreenshotDlg.h b/src/Screenshot/ScreenshotDlg.h new file mode 100644 index 0000000..eeafc8f --- /dev/null +++ b/src/Screenshot/ScreenshotDlg.h @@ -0,0 +1,31 @@ +// ScreenshotDlg.h : ͷļ +// + +#pragma once + +// CScreenshotDlg Ի +class CScreenshotDlg : public CDialog +{ +// +public: + CScreenshotDlg(CWnd* pParent = NULL); // ׼캯 + +// Ի + enum { IDD = IDD_SCREENSHOT_DIALOG }; + + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV ֧ + + +// ʵ +protected: + HICON m_hIcon; + + // ɵϢӳ亯 + virtual BOOL OnInitDialog(); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + DECLARE_MESSAGE_MAP() +public: + afx_msg void OnBnClickedBtnStart(); +}; diff --git a/src/Screenshot/res/Arrow.png b/src/Screenshot/res/Arrow.png new file mode 100644 index 0000000..de10c4f Binary files /dev/null and b/src/Screenshot/res/Arrow.png differ diff --git a/src/Screenshot/res/Arrow2.png b/src/Screenshot/res/Arrow2.png new file mode 100644 index 0000000..6266db8 Binary files /dev/null and b/src/Screenshot/res/Arrow2.png differ diff --git a/src/Screenshot/res/Brush.PNG b/src/Screenshot/res/Brush.PNG new file mode 100644 index 0000000..9f9a14e Binary files /dev/null and b/src/Screenshot/res/Brush.PNG differ diff --git a/src/Screenshot/res/Circle.png b/src/Screenshot/res/Circle.png new file mode 100644 index 0000000..65c875e Binary files /dev/null and b/src/Screenshot/res/Circle.png differ diff --git a/src/Screenshot/res/Exit.png b/src/Screenshot/res/Exit.png new file mode 100644 index 0000000..258ef8f Binary files /dev/null and b/src/Screenshot/res/Exit.png differ diff --git a/src/Screenshot/res/Finish.png b/src/Screenshot/res/Finish.png new file mode 100644 index 0000000..8f2d5bd Binary files /dev/null and b/src/Screenshot/res/Finish.png differ diff --git a/src/Screenshot/res/Mosaic.png b/src/Screenshot/res/Mosaic.png new file mode 100644 index 0000000..439f937 Binary files /dev/null and b/src/Screenshot/res/Mosaic.png differ diff --git a/src/Screenshot/res/Rectangle.png b/src/Screenshot/res/Rectangle.png new file mode 100644 index 0000000..7fd4a83 Binary files /dev/null and b/src/Screenshot/res/Rectangle.png differ diff --git a/src/Screenshot/res/Save.png b/src/Screenshot/res/Save.png new file mode 100644 index 0000000..cfef03b Binary files /dev/null and b/src/Screenshot/res/Save.png differ diff --git a/src/Screenshot/res/Screenshot.ico b/src/Screenshot/res/Screenshot.ico new file mode 100644 index 0000000..8a84ca3 Binary files /dev/null and b/src/Screenshot/res/Screenshot.ico differ diff --git a/src/Screenshot/res/Screenshot.rc2 b/src/Screenshot/res/Screenshot.rc2 new file mode 100644 index 0000000..bff2e74 --- /dev/null +++ b/src/Screenshot/res/Screenshot.rc2 @@ -0,0 +1,13 @@ +// +// Screenshot.RC2 - Microsoft Visual C++ ֱӱ༭Դ +// + +#ifdef APSTUDIO_INVOKED +#error ļ Microsoft Visual C++ ༭ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// ڴ˴ֶ༭Դ... + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Screenshot/res/Text.png b/src/Screenshot/res/Text.png new file mode 100644 index 0000000..d84bb13 Binary files /dev/null and b/src/Screenshot/res/Text.png differ diff --git a/src/Screenshot/res/Undo.png b/src/Screenshot/res/Undo.png new file mode 100644 index 0000000..2b7684c Binary files /dev/null and b/src/Screenshot/res/Undo.png differ diff --git a/src/Screenshot/res/arrow_m.cur b/src/Screenshot/res/arrow_m.cur new file mode 100644 index 0000000..ee486d3 Binary files /dev/null and b/src/Screenshot/res/arrow_m.cur differ diff --git a/src/Screenshot/res/brackground.bmp b/src/Screenshot/res/brackground.bmp new file mode 100644 index 0000000..2f297f0 Binary files /dev/null and b/src/Screenshot/res/brackground.bmp differ diff --git a/src/Screenshot/resource.h b/src/Screenshot/resource.h new file mode 100644 index 0000000..8410a85 --- /dev/null +++ b/src/Screenshot/resource.h @@ -0,0 +1,33 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Screenshot.rc +// +#define IDD_SCREENSHOT_DIALOG 102 +#define IDR_MAINFRAME 128 +#define IDD_DIALOGFORIMG 129 +#define IDB_BITMAP_BK 131 +#define IDB_ARROW 132 +#define IDC_CURSOR1 136 +#define IDB_RECTANGLE 137 +#define IDB_CIRCLE 138 +#define IDB_BRUSH 139 +#define IDB_MOSAIC 140 +#define IDB_TEXT 141 +#define IDB_UNDO 142 +#define IDB_SAVE 143 +#define IDB_EXIT 144 +#define IDB_PNG2 145 +#define IDB_FINISH 145 +#define IDC_BTN_START 1000 +#define IDC_EDIT1 1001 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 146 +#define _APS_NEXT_COMMAND_VALUE 32772 +#define _APS_NEXT_CONTROL_VALUE 1003 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Screenshot/stdafx.cpp b/src/Screenshot/stdafx.cpp new file mode 100644 index 0000000..63e7f24 --- /dev/null +++ b/src/Screenshot/stdafx.cpp @@ -0,0 +1,7 @@ +// stdafx.cpp : ֻ׼ļԴļ +// Screenshot.pch ΪԤͷ +// stdafx.obj ԤϢ + +#include "stdafx.h" + + diff --git a/src/Screenshot/stdafx.h b/src/Screenshot/stdafx.h new file mode 100644 index 0000000..4d4711a --- /dev/null +++ b/src/Screenshot/stdafx.h @@ -0,0 +1,57 @@ +// stdafx.h : ׼ϵͳļİļ +// Ǿʹõĵ +// ضĿİļ + +#pragma once + +#ifndef _SECURE_ATL +#define _SECURE_ATL 1 +#endif + +#ifndef VC_EXTRALEAN +#define VC_EXTRALEAN // Windows ͷųʹõ +#endif + +#include "targetver.h" + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // ijЩ CString 캯ʽ + +// ر MFC ijЩɷĺԵľϢ +#define _AFX_ALL_WARNINGS + +#include // MFC ͱ׼ +#include // MFC չ + + +#include // MFC Զ + + + +#ifndef _AFX_NO_OLE_SUPPORT +#include // MFC Internet Explorer 4 ؼ֧ +#endif +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC Windows ؼ֧ +#endif // _AFX_NO_AFXCMN_SUPPORT + + + + + + + + + +#ifdef _UNICODE +#if defined _M_IX86 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_IA64 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_X64 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#else +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") +#endif +#endif + + diff --git a/src/Screenshot/targetver.h b/src/Screenshot/targetver.h new file mode 100644 index 0000000..93f0450 --- /dev/null +++ b/src/Screenshot/targetver.h @@ -0,0 +1,26 @@ + +#pragma once + +// º궨Ҫƽ̨Ҫƽ̨ +// ǾӦó蹦ܵ WindowsInternet Explorer ȲƷ +// 汾ָͨ汾Ͱ汾ƽ̨пõĹܣ +// + +// ҪԵָ汾ƽ̨޸ж塣 +// йزͬƽ̨ӦֵϢο MSDN +#ifndef WINVER // ָҪƽ̨ Windows Vista +#define WINVER 0x0600 // ֵΪӦֵ Windows 汾 +#endif + +#ifndef _WIN32_WINNT // ָҪƽ̨ Windows Vista +#define _WIN32_WINNT 0x0600 // ֵΪӦֵ Windows 汾 +#endif + +#ifndef _WIN32_WINDOWS // ָҪƽ̨ Windows 98 +#define _WIN32_WINDOWS 0x0410 // ֵΪʵֵ Windows Me ߰汾 +#endif + +#ifndef _WIN32_IE // ָҪƽ̨ Internet Explorer 7.0 +#define _WIN32_IE 0x0700 // ֵΪӦֵ IE 汾 +#endif + diff --git a/src/snatshot.png b/src/snatshot.png new file mode 100644 index 0000000..c294714 Binary files /dev/null and b/src/snatshot.png differ