在.NET环境中,并没有直接的屏幕截图方法。因此,决定尝试制作一个简单的屏幕截图程序。尽管对GDI编程的了解并不多,但幸运的是,Tom Archer、James Johnson和Neil Van Note及时回答了问题。这个示例程序允许捕捉整个屏幕或当前窗口,并且允许保存图片,尽管在这里硬编码了文件名和路径,因为懒得显示保存对话框。如果反复点击截图按钮,会得到一个级联屏幕截图的奇怪效果,就像示例程序的截图所示。
快速概述:
根据要捕捉屏幕还是当前窗口,使用GetDC或GetWindowDC来获取HDC。然后调用CreateCompatibleDC来创建内存DC。使用GetSystemMetrics调用来获取屏幕的大小,然后调用CreateCompatibleBitmap来创建一个位图。然后使用SelectObject将这个位图选择到内存DC中,并保存旧的位图。使用BitBlt将屏幕或窗口内容复制到这个位图中,这个位图现在被选择到内存DC中。然后选择原始位图回到DC中,删除内存DC,释放DC,并删除位图。坦率地说,代码中并没有太多.NET的东西,但想象一下,如果不得不用C#来写这一切。想想将不得不做所有的P/Invoke,以及必须为API调用编写的所有丑陋的声明。有了MC++,就不必那么麻烦了。
完整的源代码:
源代码是自解释的。注意是如何编写WinMain的。这是因为包含了windows.h,其中WinMain已经被原型化了。
MC++
#include "stdafx.h"
#using
#using
#using
#using
#include
#include
using namespace System;
using namespace System::ComponentModel;
using namespace System::Drawing;
using namespace System::Windows::Forms;
public __gc class NForm : public Form {
public:
Button *btn;
Button *btn2;
Button *btn3;
PictureBox *pbox;
void btn_Click(Object *sender, System::EventArgs* e);
void CaptureScreen(bool FullScreen);
NForm() {
this->StartPosition = FormStartPosition::CenterScreen;
this->Text = "Capture screen - Nish for CodeProject -IJW";
this->Size = Drawing::Size(750, 550);
this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::FixedDialog;
// ...
}
};
int __stdcall WinMain(HINSTANCE,HINSTANCE,LPSTR, int) {
Application::Run(new NForm());
return 0;
}
void NForm::btn_Click(Object *sender, System::EventArgs *e) {
if (sender->Equals(btn))
CaptureScreen(true);
else {
if (sender->Equals(btn2))
CaptureScreen(false);
else
pbox->Image->Save("C:\\Z.Jpg", Drawing::Imaging::ImageFormat::Jpeg);
}
}
void NForm::CaptureScreen(bool FullScreen) {
HDC hDC;
if (FullScreen)
hDC = GetDC(NULL);
else {
HWND hWnd=(HWND)this->Handle.ToInt32();
hDC = GetWindowDC(hWnd);
}
HDC hMemDC = CreateCompatibleDC(hDC);
RECT r;
GetWindowRect((HWND)this->Handle.ToInt32(),&r);
SIZE size;
if (FullScreen) {
size.cx = GetSystemMetrics(SM_CXSCREEN);
size.cy = GetSystemMetrics(SM_CYSCREEN);
}
else {
size.cx = r.right-r.left;
size.cy = r.bottom-r.top;
}
HBITMAP hBitmap = CreateCompatibleBitmap(hDC, size.cx, size.cy);
if (hBitmap) {
HBITMAP hOld = (HBITMAP) SelectObject(hMemDC, hBitmap);
BitBlt(hMemDC, 0, 0, size.cx, size.cy, hDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, hOld);
DeleteDC(hMemDC);
ReleaseDC(NULL, hDC);
pbox->Image = Image::FromHbitmap(hBitmap);
DeleteObject(hBitmap);
}
}