[关于窗口刷新]新手MFC做截图软件求助

d1wwww23123123 2012-08-27 07:56:29
// FullScreenDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "ScreenCat.h"
#include "FullScreenDlg.h"
#include "ScreenCat.h"
#include <atlimage.h>

// CFullScreenDlg 对话框

IMPLEMENT_DYNAMIC(CFullScreenDlg, CDialog)

CFullScreenDlg::CFullScreenDlg(CWnd* pParent /*=NULL*/)
: CDialog(CFullScreenDlg::IDD, pParent)
{
//初始化m_tracker对象
m_tracker.m_rect.SetRect(-1, -2, -3, -4);
//初始边界形式
m_tracker.m_nStyle=CRectTracker::resizeOutside|CRectTracker::solidLine;
m_tracker.m_nHandleSize = 8;

//获取屏幕分辩率
m_xScreen = GetSystemMetrics(SM_CXSCREEN);
m_yScreen = GetSystemMetrics(SM_CYSCREEN);
//拷贝屏幕
CRect rect(0, 0,m_xScreen,m_yScreen);

hbitmap=CopyScreenToBitmap(&rect);
}

CFullScreenDlg::~CFullScreenDlg()
{

}

void CFullScreenDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BOOL CFullScreenDlg::OnInitDialog()
{
CDialog::OnInitDialog();

//把对化框设置成全屏顶层窗口

SetWindowPos(&wndTopMost,0,0,m_xScreen,m_yScreen,SWP_SHOWWINDOW);
return TRUE;
}


//此函数将被调用两次 第一次传递屏幕矩形 第二次传递截取矩形
HBITMAP CFullScreenDlg::CopyScreenToBitmap(LPRECT lpRect)
{
HDC hScrDC, hMemDC;
// 屏幕和内存设备描述表
HBITMAP hBitmap, hOldBitmap;
// 位图句柄
int nX, nY, nX2, nY2;
// 选定区域坐标
int nWidth, nHeight;

// 确保选定区域不为空矩形
if (IsRectEmpty(lpRect))
return NULL;
//为屏幕创建设备描述表
hScrDC = CreateDC("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);
// 把屏幕设备描述表拷贝到内存设备描述表中
BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY);
hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
//得到屏幕位图的句柄
//清除
DeleteDC(hScrDC);
DeleteDC(hMemDC);

return hBitmap;
}




BEGIN_MESSAGE_MAP(CFullScreenDlg, CDialog)

ON_WM_PAINT()
ON_WM_RBUTTONDOWN()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONDBLCLK()

END_MESSAGE_MAP()


// CFullScreenDlg 消息处理程序


void CFullScreenDlg::OnPaint()
{


CPaintDC dc(this);
HDC hdc=CreateCompatibleDC(dc);
SelectObject(hdc,hbitmap);
BitBlt(dc.m_hDC,0,0,m_xScreen,m_yScreen,hdc,0,0,SRCCOPY);

//画出矩形框
m_tracker.Draw(&dc);


// device context for painting
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CDialog::OnPaint()
}

void CFullScreenDlg::OnRButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if(m_tracker.HitTest(point) < 0 )//当在矩形外右击时,返回主窗口
{
CDialog::OnOK();
GetParent()->ShowWindow(SW_SHOW);
}
else //在矩形内右击,保存文件 再返回主界面
{
SaveToFile(CopyScreenToBitmap(m_tracker.m_rect));

CDialog::OnOK();
GetParent()->ShowWindow(SW_SHOW);
}
CDialog::OnRButtonDown(nFlags, point);
}

void CFullScreenDlg::OnLButtonDown(UINT nFlags, CPoint point)
{

// TODO: 在此添加消息处理程序代码和/或调用默认值
if(m_tracker.HitTest(point) < 0 ) // 点击在矩形外部 画选择框
{
m_tracker.TrackRubberBand(this,point,TRUE);
m_tracker.m_rect.NormalizeRect();
}
else // 点矩形选择框
{
m_tracker.Track(this,point,TRUE);
m_tracker.m_rect.NormalizeRect();
}

Invalidate(); //使客户区无效 系统会自动刷新窗口
CDialog::OnLButtonDown(nFlags, point);
}

void CFullScreenDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值

//如果在是矩形内部双击
if( m_tracker.HitTest(point) == 8)
{
if (OpenClipboard())
{
EmptyClipboard();
SetClipboardData(CF_BITMAP, CopyScreenToBitmap(m_tracker.m_rect) );
CloseClipboard();
}

CDialog::OnOK();
GetParent()->ShowWindow(SW_SHOW);

}

CDialog::OnLButtonDblClk(nFlags, point);


}


void CFullScreenDlg::SaveToFile(HBITMAP hBitmap)
{

}



纯新手,完全没用过mfc,没做过图形编程。因此做了大量注释。
很多函数都是网上搜了自己改的。目前只是实现了一点功能。
遇到了一个关于窗口刷新的问题,导致截图不能很好地实现。

问题:
1、我想用橡皮筋类来实现在窗口上画矩形框的功能。代码写在了OnLButtonDown()里。其中有这样一句Invalidate();即强制刷新了窗口以便能够在窗口上画出矩形。
结果运行程序,发现只在一个白色的窗口上画了矩形。
目前已知:调用Invalidate()后确实执行了OnPaint(),但OnPaint()里把当前屏幕位图设为窗口背景却没有实现。
而初始化时,是可以把屏幕位图作为背景的。
2、当不把对话框设置为全屏置顶窗口时,虽然窗口完全是白色的,但截到的图却是正常的。把对话框设成全屏置顶窗口后,窗口是白色的,截图也是白色。

3、上面的问题如何解决?另:写的很水的地方,希望大家指正。

...全文
255 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
d1wwww23123123 2012-08-28
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

引用 3 楼 的回复:

把Invalidate()注释掉之后,画橡皮筋时有个虚线框,但是松开鼠标,矩形就消失了,点击区域区域倒是可以拖动矩形。……


松开鼠标,矩形就消失,但你已经获得矩形,此时就对该矩形进行操作,比如复制该矩形图形。
[/Quote]
的确,按我的程序,此时双击已经能复制到剪切板了。但是不能进行对矩形的调整,只有画出橡皮筋矩形的时候才能在边框各个位置进行不同调整。

能给我说一下为什么执行Invalidate()后,对话框背景没有显示,但却画出矩形了么?
看说明是Invalidate()使用户区无效从而迫使窗口进行重绘,应该会执行OnPaint();
而初始化窗口的时候执行OnPaint()是可以将屏幕设为对话框背景的,为什么现在就不行了?
罗平 2012-08-27
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

把Invalidate()注释掉之后,画橡皮筋时有个虚线框,但是松开鼠标,矩形就消失了,点击区域区域倒是可以拖动矩形。……
[/Quote]

松开鼠标,矩形就消失,但你已经获得矩形,此时就对该矩形进行操作,比如复制该矩形图形。
d1wwww23123123 2012-08-27
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

可以用两个DC实现。
屏幕图像保存到 DC1,
矩形操作在对话框DC2,
同时显示到全屏对话框(DC2),可以用半透明通道(AlphaBlend)阴影遮罩对话DC2,类似QQ截图阴影遮罩。

橡皮筋不要 Invalidate,他会自动有一个虚线显示当前矩形。
获得橡皮筋所选矩形,到DC1相对应的矩形获得图片。并填充当前对话框DC中的选择矩形部分。
[/Quote]
把Invalidate()注释掉之后,画橡皮筋时有个虚线框,但是松开鼠标,矩形就消失了,点击区域区域倒是可以拖动矩形。
  • 打赏
  • 举报
回复
CopyScreenToBitmap的结果要在OnPaint中绘制
罗平 2012-08-27
  • 打赏
  • 举报
回复
可以用两个DC实现。
屏幕图像保存到 DC1,
矩形操作在对话框DC2,
同时显示到全屏对话框(DC2),可以用半透明通道(AlphaBlend)阴影遮罩对话DC2,类似QQ截图阴影遮罩。

橡皮筋不要 Invalidate,他会自动有一个虚线显示当前矩形。
获得橡皮筋所选矩形,到DC1相对应的矩形获得图片。并填充当前对话框DC中的选择矩形部分。

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧