急求高手看看我的截图程序 为什么运行后没效果

sunshineJ313 2010-04-29 05:50:13

BOOL CScreenDlg::OnInitDialog()
{
CDialog::OnInitDialog();
m_bDraw=false;
//使窗口变成透明
this->ShowWindow(SW_MAXIMIZE);
//加入WS_EX_LAYERED扩展属性,必须要加上这个属性
SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^0x80000);

//调用User32.DLL中的函数
HINSTANCE hInst = LoadLibrary("User32.DLL");
if(hInst)
{
typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD);
MYFUNC fun = NULL;
//取得SetLayeredWindowAttributes函数指针
fun=(MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");
if(fun)fun(this->GetSafeHwnd(),0,100,2);
FreeLibrary(hInst);
}
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}


void CScreenDlg::OnLButtonDown(UINT nFlags, CPoint point) //鼠标左键按下消息处理
{
// TODO: Add your message handler code here and/or call default
m_bDraw=true;

GetCursorPos(&(this->startPt));
GetCursorPos(&(this->endPt));
CDialog::OnLButtonDown(nFlags, point);
}

void CScreenDlg::OnLButtonUp(UINT nFlags, CPoint point) //鼠标左键弹起消息处理
{
// TODO: Add your message handler code here and/or call default
m_bDraw=false;
GetCursorPos(&(this->endPt));
CRect rect(this->startPt.x,this->startPt.y,this->endPt.x,this->endPt.y);
CClientDC dc(this);
CDialog::OnLButtonUp(nFlags, point);
}

void CScreenDlg::OnMouseMove(UINT nFlags, CPoint point) //鼠标移动消息处理
{
// TODO: Add your message handler code here and/or call default
if(m_bDraw)
{
HDC hdc=::GetDC(this->GetSafeHwnd());
SetROP2(hdc,R2_NOTXORPEN);

HPEN hpen;
hpen=CreatePen(PS_SOLID,2,RGB(255,0,0));
SelectObject(hdc,hpen);
SelectObject(hdc,GetStockObject(NULL_BRUSH));
::Rectangle(hdc,this->startPt.x,this->startPt.y,this->endPt.x,this->endPt.y);
// endPt=point;
GetCursorPos(&(this->endPt));
::Rectangle(hdc,this->startPt.x,this->startPt.y,this->endPt.x,this->endPt.y);
::ReleaseDC(this->GetSafeHwnd(),hdc);
::DeleteObject(hpen);
}
CDialog::OnMouseMove(nFlags, point);
}



HBITMAP CScreenDlg::CopyScreenToBitmap(LPRECT lpRect) // 将屏幕上的截取区域转化至位图
{
HDC hScrDC, hMemDC;
HBITMAP hOldBitmap,hBitmap;
int nX, nY, nX2, nY2;
int nWidth, nHeight;
int xScrn, yScrn;
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;
xScrn = GetDeviceCaps(hScrDC, HORZRES);
yScrn = GetDeviceCaps(hScrDC, VERTRES);
if (nX < 0) nX = 0;
if (nY < 0) nY = 0;
if (nX2 > xScrn) nX2 = xScrn;
if (nY2 > yScrn) nY2 = yScrn;
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;

}

void CScreenDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
// ShowWindow(SW_HIDE);
CRect rect;
rect.bottom=(this->endPt.y>this->startPt.y)?this->endPt.y:this->startPt.y;
rect.left=(this->startPt.x<this->endPt.x)?this->startPt.x:this->endPt.x;
rect.right=(this->endPt.x>this->startPt.x)?this->endPt.x:this->startPt.x;
rect.top=(this->startPt.y<this->endPt.y)?this->startPt.y:this->endPt.y;
HBITMAP hBitmap=CopyScreenToBitmap(&rect);
if (OpenClipboard()) //将截取的图像放在剪切板上
{
EmptyClipboard();
SetClipboardData(CF_BITMAP, hBitmap);
CloseClipboard();
}
ShowWindow(SW_SHOW);
this->EndDialog(0);

HBITMAP handle=(HBITMAP)GetClipboardData(CF_BITMAP); //将剪切板上的位图显示在客户区
CBitmap* bm=CBitmap::FromHandle(hBitmap);

CClientDC cdc(this);
CDC dc;
dc.CreateCompatibleDC(&cdc);
dc.SelectObject(bm);
cdc.BitBlt(0,0,200,200,&dc,0,0,SRCCOPY);


CDialog::OnLButtonDblClk(nFlags, point);
}


本程序最后实现的功能是将截取的图显示在客户区,其实我想做的是图像显示在一个新建的文档里的,但在客户区都无法显示,我不知该怎么办啊? 我想问题可能出在 矩形区域的图像到底被截取没有
剪切板上到底有没有位图
麻烦哪位看一下 我都整了几天了 谢谢各位了!
...全文
248 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
sunshineJ313 2010-05-02
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 fireway2008 的回复:]
请查看15楼中我给你的那个链接,

人家已经是成品的东西了,可以拿来就用,建议你先参考一下。
[/Quote]

大哥!我发现我矩形区域画错了的 已改正!能截图了!谢谢你的帮助啊!以后多交流啊!结贴!
Fireway2008 2010-05-01
  • 打赏
  • 举报
回复
请查看15楼中我给你的那个链接,

人家已经是成品的东西了,可以拿来就用,建议你先参考一下。
sunshineJ313 2010-05-01
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 fireway2008 的回复:]
请在你的OnMouseMove
内添加一个断点,然后调试看看是什么地方出了问题.
[/Quote]

我调试了的 好像提示图像信息头(LPBITMAPINFOHEADER)那里有问题的 不懂了!!!!!
sunshineJ313 2010-05-01
  • 打赏
  • 举报
回复
你好!幽幽心源 我认为问题是当我双击鼠标左键后,根本无法捕捉到我画的矩形区域。我是在一个透明的窗口上绘制矩形的,与这有关系吗?有的人说用鼠标拖动选取截图范围时不是在选择屏幕,而是在一张固定的大图上面“裁剪”小图。 兄弟!你能把你的邮箱给我吗?我发给麻烦你看看啊!谢谢了啊!
以下是捕捉全屏的代码,就可以捕获到的
CRect rect;
rect.left = 0;
rect.top = 0;
rect.right = GetSystemMetrics(SM_CXSCREEN);
rect.bottom = GetSystemMetrics(SM_CYSCREEN);
当换成我的矩形区域后 就不得行了
rect.bottom=(this->endPt.y>this->startPt.y)?this->endPt.y:this->startPt.y;
rect.left=(this->startPt.x<this->endPt.x)?this->startPt.x:this->endPt.x;
rect.right=(this->endPt.x>this->startPt.x)?this->endPt.x:this->startPt.x;
rect.top=(this->startPt.y<this->endPt.y)?this->startPt.y:this->endPt.y;

Fireway2008 2010-05-01
  • 打赏
  • 举报
回复
请在你的OnMouseMove
内添加一个断点,然后调试看看是什么地方出了问题.
sunshineJ313 2010-04-30
  • 打赏
  • 举报
回复
我想问问各位 我将选择区域存成图片 也就是用程序中的CopyScreenToBitmap来实现的 请问此时图片是在内存里面吗? 那么再将内存的图片显示 保存可以吗?
wangyingyingqq 2010-04-30
  • 打赏
  • 举报
回复
友情帮顶
sunshineJ313 2010-04-30
  • 打赏
  • 举报
回复
我刚刚试过了,截取整个屏幕保存成文件可以实现了,但是当我添加区域截图的相关程序后(即在屏幕上画矩形区域),就提示出错。各位看看这是什么问题的?

以下代码是对窗口的消息响应 ,能实现画矩形区域的
void CScreenDlg::OnLButtonDown(UINT nFlags, CPoint point) //鼠标左键按下
{
// TODO: Add your message handler code here and/or call default
m_bDraw=true;
startPt=endPt=point;
CDialog::OnLButtonDown(nFlags, point);
}

void CScreenDlg::OnLButtonUp(UINT nFlags, CPoint point) //鼠标左键弹起
{
// TODO: Add your message handler code here and/or call default
m_bDraw=false;
endPt=point;
CRect rect(this->startPt.x,this->startPt.y,this->endPt.x,this->endPt.y);
CClientDC dc(this);
CDialog::OnLButtonUp(nFlags, point);
}

void CScreenDlg::OnMouseMove(UINT nFlags, CPoint point) //鼠标移动
{
// TODO: Add your message handler code here and/or call default
if(m_bDraw)
{
HDC hdc=::GetDC(this->GetSafeHwnd());
SetROP2(hdc,R2_NOTXORPEN);

HPEN hpen;
hpen=CreatePen(PS_SOLID,2,RGB(255,0,0));
SelectObject(hdc,hpen);
SelectObject(hdc,GetStockObject(NULL_BRUSH));
::Rectangle(hdc,this->startPt.x,this->startPt.y,this->endPt.x,this->endPt.y);
endPt=point;
::Rectangle(hdc,this->startPt.x,this->startPt.y,this->endPt.x,this->endPt.y);
::ReleaseDC(this->GetSafeHwnd(),hdc);
::DeleteObject(hpen);
}
CDialog::OnMouseMove(nFlags, point);
}

void CScreenDlg::OnLButtonDblClk(UINT nFlags, CPoint point) //鼠标双击
{
// TODO: Add your message handler code here and/or call default

CRect rect;
rect.bottom=(this->endPt.y>this->startPt.y)?this->endPt.y:this->startPt.y;
rect.left=(this->startPt.x<this->endPt.x)?this->startPt.x:this->endPt.x;
rect.right=(this->endPt.x>this->startPt.x)?this->endPt.x:this->startPt.x;
rect.top=(this->startPt.y<this->endPt.y)?this->startPt.y:this->endPt.y;
HBITMAP hMap = CopyScreenToBitmap(&rect);
SaveBitmapToFile(hMap,"C:\\截屏.bmp");
this->EndDialog(0);

CDialog::OnLButtonDblClk(nFlags, point);
}
sunshineJ313 2010-04-30
  • 打赏
  • 举报
回复
回15楼的
我用的方法 Ctrl+V后 提示 “获取剪切板的数据错误”字样,难道是剪切板上没东西吗?
Fireway2008 2010-04-30
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 sunshinej313 的回复:]
我想问问各位 我将选择区域存成图片 也就是用程序中的CopyScreenToBitmap来实现的 请问此时图片是在内存里面吗? 那么再将内存的图片显示 保存可以吗?
[/Quote]

对,此时还是内存的数据。
你想知道位图是否保存入剪切板了,可以打开Windows自带的画图工具,在其中的空白画布里边,Ctrl+V就可以看到效果。


另外,给你推荐一个截图的程序参考:QQ 静态截图程序模拟实现

至于如何将内存中的数据转换成磁盘文件保存,推荐一个FreeImage 类库,里边封装很多图像处理的功能。
schlafenhamster 2010-04-30
  • 打赏
  • 举报
回复
你截图后,调copy就到剪贴板了,再调paste就取到了
Eleven 2010-04-29
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 sunshinej313 的回复:]
1楼的 你能给我保存到文件的源码吗?我也想啊 没弄出来的 只晓得新建文件 不知如何将图片放到里面去
[/Quote]

void SaveScreen(LPCTSTR lpszFilePath)
{
TCHAR szPath[MAX_PATH] = {0};
if(NULL == lpszFilePath)
{
GetModuleFileName(NULL, szPath, MAX_PATH-1);
LPTSTR lpszPath = _tcschr(szPath, _T('\\'));
LPTSTR lpszEnd = szPath;
while(NULL != lpszPath)
{
lpszEnd = lpszPath;
lpszPath = _tcschr(lpszPath+1, _T('\\'));
}
int nPos = lpszEnd - szPath + 1;
szPath[nPos] = _T('\0');
CString strPath(szPath);

LPCTSTR lpszFile = _T("PICTURES");
strPath += lpszFile;
if(!PathFileExists(strPath))
{
if(CreateDirectory(strPath, NULL))
{
return ;
}
}
_stprintf_s(_tcschr(szPath, _T('\0')), _countof(szPath) - _tcslen(szPath), _T("%s\\CS_%05d.bmp"), lpszFile, ++m_nIndex);
}
else
{
_stprintf_s(szPath, sizeof(szPath), _T("%s"), lpszFilePath);
}

if(0 != _tcslen(szPath))
{
CDC* pDC = CDC::FromHandle(::GetDC(NULL));
int nBitsPixel = pDC->GetDeviceCaps(BITSPIXEL);
int nWidth = pDC->GetDeviceCaps(HORZRES);
int nHeight = pDC->GetDeviceCaps(VERTRES);

CDC memDC;
memDC.CreateCompatibleDC(pDC);

CBitmap bitmap;
bitmap.CreateCompatibleBitmap(pDC, nWidth, nHeight);

CBitmap* oldBmp = memDC.SelectObject(&bitmap);
memDC.BitBlt(0, 0, nWidth, nHeight, pDC, 0, 0, SRCCOPY);

BITMAP bmp;
bitmap.GetBitmap(&bmp);

try
{
CFile file;
file.Open(szPath, CFile::modeCreate | CFile::typeBinary | CFile::modeWrite);

BITMAPINFOHEADER bih = {0};
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biBitCount = bmp.bmBitsPixel;
bih.biCompression = BI_RGB;
bih.biHeight = bmp.bmHeight;
bih.biPlanes = 1;
bih.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;
bih.biWidth = bmp.bmWidth;

BITMAPFILEHEADER bfh = {0};
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bfh.bfSize = bfh.bfOffBits + bmp.bmWidthBytes * bmp.bmHeight;
bfh.bfType = (WORD)0x4d42;
file.Write(&bfh, sizeof(BITMAPFILEHEADER));
file.Write(&bih, sizeof(BITMAPINFOHEADER));
BYTE* pByte = new BYTE[bmp.bmWidthBytes * bmp.bmHeight];
GetDIBits(memDC.m_hDC, (HBITMAP)bitmap.m_hObject, 0, nHeight, pByte, (LPBITMAPINFO)&bih, DIB_RGB_COLORS);
file.Write(pByte, bmp.bmWidthBytes * bmp.bmHeight);
file.Flush();
file.Close();
delete[] pByte;
}
catch (CFileException* e)
{
e->ReportError();
e->Delete();
}

memDC.SelectObject(oldBmp);
bitmap.DeleteObject();
memDC.DeleteDC();
}
}
sunshineJ313 2010-04-29
  • 打赏
  • 举报
回复
hBitmap=CreateCompatibleBitmap(hScrDC,nWidth,nHeight); 这句没错啊 为什么要改成hMemDC

请指点!!!!
sunshineJ313 2010-04-29
  • 打赏
  • 举报
回复
schlafenhamster
你的这段程序加到哪里啊? 请表明下嘛 谢啦!
sunshineJ313 2010-04-29
  • 打赏
  • 举报
回复
1楼的 你能给我保存到文件的源码吗?我也想啊 没弄出来的 只晓得新建文件 不知如何将图片放到里面去
schlafenhamster 2010-04-29
  • 打赏
  • 举报
回复
//少2句
// make bitmap
HGLOBAL hHeader=::GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE|GMEM_ZEROINIT,sizeof(BITMAPINFOHEADER)+
sizeof(colors)+bytesperline*m_GlyphSize);//
BYTE *pHeader=(BYTE*)::GlobalLock(hHeader);
ASSERT(pHeader!=NULL);
。。。//接上贴
schlafenhamster 2010-04-29
  • 打赏
  • 举报
回复
//paste
// put into gmem
memcpy(pHeader,&BMPinfo.bmiHeader,sizeof(BITMAPINFOHEADER));
memcpy(pHeader+sizeof(BITMAPINFOHEADER),colors,sizeof(colors));
memcpy((BYTE*)pHeader+sizeof(BITMAPINFOHEADER)+sizeof(colors),&DIBs,bytesperline*m_GlyphSize);
SetClipboardData(CF_DIB,pHeader);// clip board will delete this
::GlobalUnlock(hHeader);
CloseClipboard();
尹成 2010-04-29
  • 打赏
  • 举报
回复
hBitmap=CreateCompatibleBitmap(hScrDC,nWidth,nHeight);
这句改为:
hBitmap=CreateCompatibleBitmap(hMemDC,nWidth,nHeight);
schlafenhamster 2010-04-29
  • 打赏
  • 举报
回复
if (!OpenClipboard()) return;
// if nothing
if (!(pbmpInfo = (BITMAPINFO*)GetClipboardData(CF_DIB)))
{
goto exit;
}
//不是CF_BITMAP !!!
天鹅梦 2010-04-29
  • 打赏
  • 举报
回复
hBitmap=CreateCompatibleBitmap(hScrDC,nWidth,nHeight);
这句改为:
hBitmap=CreateCompatibleBitmap(hMemDC,nWidth,nHeight);
加载更多回复(2)

19,468

社区成员

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

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