//
#include "stdafx.h"
#include "Win32Project2.h"
#define MAX_LOADSTRING 100
// 全局变量:
HINSTANCE hInst; // 当前实例
TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
HDC g_srcMemDc; // - 源桌面截图
HDC g_grayMemDc; // - 灰度桌面截图
int screenW; // - 电脑屏幕的宽
int screenH; // - 电脑屏幕的高
RECT rect = { 0 }; // - 画图的矩形区域
bool isSelect = false; // - 是否已经选中区域
bool isDown = false; // - 是否已经按下左键
// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 在此放置代码。
MSG msg;
HACCEL hAccelTable;
// 初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_WIN32PROJECT2, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_POPUP,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
ShowWindow(hWnd, SW_MAXIMIZE);
// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32PROJECT2));
// 主消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// 函数: MyRegisterClass()
//
// 目的: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32PROJECT2));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = 0;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// 函数: InitInstance(HINSTANCE, int)
//
// 目的: 保存实例句柄并创建主窗口
//
// 注释:
//
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // 将实例句柄存储在全局变量中
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目的: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
void CovertToGrayBitmap(HBITMAP hSourceBmp, HDC sourceDc)
{
HBITMAP retBmp = hSourceBmp;
BITMAPINFO bmpInfo;
ZeroMemory(&bmpInfo, sizeof(BITMAPINFO));
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
GetDIBits(sourceDc, retBmp, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS);
BYTE* bits = new BYTE[bmpInfo.bmiHeader.biSizeImage];
GetBitmapBits(retBmp, bmpInfo.bmiHeader.biSizeImage, bits);
int bytePerPixel = 4;//默认32位
if (bmpInfo.bmiHeader.biBitCount == 24)
{
bytePerPixel = 3;
}
for (DWORD i = 0; i<bmpInfo.bmiHeader.biSizeImage; i += bytePerPixel)
{
BYTE r = *(bits + i);
BYTE g = *(bits + i + 1);
BYTE b = *(bits + i + 2);
*(bits + i) = *(bits + i + 1) = *(bits + i + 2) = (r + b + g) / 3;
}
SetBitmapBits(hSourceBmp, bmpInfo.bmiHeader.biSizeImage, bits);
delete[] bits;
}
void ScreenCapture()
{
HDC disDc = CreateDC(L"DISPLAY", 0, 0, 0); // - 创建一个DC,与桌面相关的
screenW = GetDeviceCaps(disDc, HORZRES); // - 水平分辨率
screenH = GetDeviceCaps(disDc, VERTRES); // - 垂直分辨率
//获取桌面截图
g_srcMemDc = CreateCompatibleDC(disDc); // - 创建一个兼容DC(内存DC),与桌面DC相关的
HBITMAP hbitMap = CreateCompatibleBitmap(disDc, screenW, screenH); // - 模拟一张画布,其中没有数据
SelectObject(g_srcMemDc, hbitMap); // - 将画布选入内存DC,其中还是没有数据
//将桌面画到画布上,将屏幕的dc中的画图,拷贝至内存DC中
BitBlt(g_srcMemDc, 0, 0, screenW, screenH, disDc, 0, 0, SRCCOPY); // - 整个桌面被画到memDc上
//获取屏幕的灰度图片
g_grayMemDc = CreateCompatibleDC(disDc); // - 创建一个兼容DC,存放灰度图片
HBITMAP grayMap = CreateCompatibleBitmap(disDc, screenW, screenH); // - 模拟一张画布,其中没有数据
SelectObject(g_grayMemDc, grayMap); // - 将画图选入内存DC,其中还是没有数据的
BitBlt(g_grayMemDc, 0, 0, screenW, screenH, disDc, 0, 0, SRCCOPY); // - 将屏幕的dc中的画图,拷贝至内存DC中
CovertToGrayBitmap(grayMap, g_grayMemDc); // - 将彩色图片转换为灰度图片
DeleteObject(hbitMap);
DeleteObject(grayMap);
DeleteObject(disDc);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT: // - 屏幕绘制消息,画线条,画图片
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps); // - 代表当前窗口
//将灰度图像和变亮部分画到memDc中(兼容DC)
HDC memDc = CreateCompatibleDC(hdc);
HBITMAP bmp = CreateCompatibleBitmap(hdc, screenW, screenH);
SelectObject(memDc, bmp);
BitBlt(memDc, 0, 0, screenW, screenH, g_grayMemDc, 0, 0, SRCCOPY);
SelectObject(memDc, hBrush);
SelectObject(memDc, hPen);
if (isDown || isSelect)
{
BitBlt(memDc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, g_srcMemDc, rect.left, rect.top, SRCCOPY);// - 选中的区域变亮,将变亮的部分画到memDc
Rectangle(memDc, rect.left, rect.top, rect.right, rect.bottom);// - 画矩形
}
//最后将灰度和变亮的部分一起画到桌面
BitBlt(hdc, 0, 0, screenW, screenH, memDc, 0, 0, SRCCOPY);
DeleteObject(bmp);
DeleteObject(memDc);
EndPaint(hWnd, &ps);
}
break;
case WM_MOUSEMOVE:
{
if (isDown && !isSelect)
{
POINT pt;
GetCursorPos(&pt);
rect.right = pt.x;
rect.bottom = pt.y;
InvalidateRgn(hWnd, 0, false);
}
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
ScreenCapture();
break;
case WM_LBUTTONDBLCLK: // - 双击复制
{
POINT pt;
GetCursorPos(&pt);
if (PtInRect(&rect, pt))
{
if (isSelect) // - 选中区域了才去拷贝
{
CopyBitmapToClipBoard(); // - 拷贝选中区域到粘贴板
}
}
InvalidateRgn(hWnd, 0, false);
ShowWindow(hWnd, SW_MINIMIZE);
isDown = false;
isSelect = false;
}
break;
case WM_LBUTTONDOWN:
{
if (!isSelect) // - 如果没有选中才能按左键
{
POINT pt;
GetCursorPos(&pt); // - 得到当前光标位置
rect.left = pt.x;
rect.top = pt.y;
rect.right = pt.x;
rect.bottom = pt.y;
InvalidateRgn(hWnd, 0, false);
isDown = true;
}
}
break;
case WM_LBUTTONUP:
{
if (isDown == TRUE &&!isSelect) // - 鼠标按下了才计算矩形大小
{
POINT pt;
GetCursorPos(&pt); // - 得到当前光标位置
rect.right = pt.x;
rect.bottom = pt.y;
InvalidateRgn(hWnd, 0, false);
isSelect = true; // - 弹起的时候,表示区域已经选中
}
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
1>------ 已启动生成: 项目: Win32Project2, 配置: Debug Win32 ------
1> stdafx.cpp
1> Win32Project2.cpp
1>c:\users\think\documents\visual studio 2013\projects\win32project2\win32project2\win32project2.cpp(223): error C2065: “hBrush”: 未声明的标识符
1>c:\users\think\documents\visual studio 2013\projects\win32project2\win32project2\win32project2.cpp(224): error C2065: “hPen”: 未声明的标识符
1>c:\users\think\documents\visual studio 2013\projects\win32project2\win32project2\win32project2.cpp(264): error C3861: “CopyBitmapToClipBoard”: 找不到标识符
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========
我照着打造自己的屏幕截图软件(QQ截图功能实现)出现了问题
C++技术网会员解答:
感谢您对C++技术网的支持。
未声明的标识符,意思是找不到这些标志符的定义。代码只是直接用了这些标志符。至于这些标志符未定义,不是问题,而是写代码是应该就先定义好的。对于变量,可以自己在使用前定义一下。而对于函数,则需要查找对应的头文件,并包含到代码中。函数的头文件,请使用MSDN来查询函数,并找到对应的头文件。
别人分享的代码,可能只是给了核心的代码,一些细节丢失,都是很正常的,需要你自己去根据错误提示来补全代码,而作者分享的目的也应该是能够补全代码的人。如果基本的代码无法完成补全修复错误,可能你现在就无法读懂代码。
此程序代码是Win32程序代码,如果不熟悉Windows编程,推荐书籍《Windows程序设计》,再配合阅读C++技术网win32教程《Windows零基础入门教程》。