鱼C论坛

 找回密码
 立即注册
查看: 4685|回复: 20

[原创] C语言制作的简单的截屏器

[复制链接]
发表于 2016-6-19 19:02:51 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 无符号整形 于 2016-6-19 20:09 编辑

这个截屏器简单又粗糙,还有一个小bug,但是它也许能让你研究很久。哈哈~

好吧直接上图上代码,有个小bug,请仔细观察。
gggg.JPG
很粗糙吧!
截图效果:
ggggg.JPG
发现bug了吧。。。还有那个小安仔,还挺好玩的:-)
代码:
#include <windows.h>
#include "resource.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);        //声明用来处理消息的函数
HBITMAP CaptureScreen(LPRECT);
BOOL SaveBmp(HBITMAP, const char*);
HINSTANCE g_hInstance;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
        static TCHAR szAppName[] = TEXT("MyWindow");
        HWND hwnd;
        MSG msg;
        WNDCLASS wndclass;        //声明一个窗口类对象
        
        HMENU hMenu = CreateMenu();
        HMENU hMenuPopup = CreateMenu();
        AppendMenu(hMenuPopup, MF_STRING, 100, "截屏");
        AppendMenu(hMenuPopup, MF_STRING, 101, "另存为");
        AppendMenu(hMenuPopup, MF_STRING, 103, "延时3秒并截屏");
        AppendMenu(hMenu, MF_POPUP, (ULONG_PTR)hMenuPopup, "截屏");
        //以下为窗口类对象wndclass的属性
        wndclass.style = CS_HREDRAW | CS_VREDRAW;                         //窗口样式
        wndclass.lpszClassName = szAppName;                               //窗口类名
        wndclass.lpszMenuName = NULL;                                     //窗口菜单:无
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);    //窗口背景颜色
        wndclass.lpfnWndProc = WndProc;                                   //窗口处理函数
        wndclass.cbWndExtra = 0;                                          //窗口实例扩展:无
        wndclass.cbClsExtra = 0;                                          //窗口类扩展:无
        wndclass.hInstance = hInstance;                                   //窗口实例句柄
        wndclass.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));               //窗口最小化图标:使用缺省图标
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);                 //窗口采用箭头光标

        if (!RegisterClass(&wndclass))
        {    //注册窗口类, 如果注册失败弹出错误提示
                MessageBox(NULL, TEXT("窗口注册失败!"), TEXT("错误"), MB_OK | MB_ICONERROR);
                return 0;
        }

        hwnd = CreateWindow(                   //创建窗口
                szAppName,                 //窗口类名
                TEXT("截图工具"),           //窗口标题
                WS_OVERLAPPEDWINDOW,       //窗口的风格
                CW_USEDEFAULT,             //窗口初始显示位置x:使用缺省值
                CW_USEDEFAULT,             //窗口初始显示位置y:使用缺省值
                400,             //窗口的宽度:使用缺省值
                100,             //窗口的高度:使用缺省值
                NULL,                      //父窗口:无
                hMenu,                      //子菜单:无
                hInstance,                 //该窗口应用程序的实例句柄 
                NULL                       //
                );
        g_hInstance = hInstance;
        ShowWindow(hwnd, iCmdShow);        //显示窗口
        UpdateWindow(hwnd);                //更新窗口

        while (GetMessage(&msg, NULL, 0, 0))        //从消息队列中获取消息
        {
                TranslateMessage(&msg);                 //将虚拟键消息转换为字符消息
                DispatchMessage(&msg);                  //分发到回调函数(过程函数)
        }
        return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        HDC hdc, hdcMem;
        static RECT rect;
        static HBITMAP hBitmap;
        static int cx,cy;
        BITMAP bitmap;
        static OPENFILENAME ofn;
        static TCHAR szBuffer[1000] = "";
        static LONG xPos, yPos;
        PAINTSTRUCT ps;
        ofn.lStructSize = sizeof(OPENFILENAME);
        ofn.lpstrFilter = "bmp";
        ofn.lpstrInitialDir = NULL;
        ofn.lpstrFile = szBuffer;
        ofn.nMaxFile = sizeof(szBuffer) / sizeof(*szBuffer);
        ofn.nFilterIndex = 0;
        ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER;

        switch (message)        //处理得到的消息
        {
        case WM_COMMAND:

                switch (LOWORD(wParam))
                {
                case 100:
                        SetCursor(LoadCursor(g_hInstance, IDC_WAIT));
                        MoveWindow(hwnd, 0, 0, 0, 0, 0);
                        ShowWindow(hwnd, SW_HIDE);
                        hBitmap = CaptureScreen(NULL);
                        ShowWindow(hwnd, SW_SHOW);
                        SetCursor(LoadCursor(g_hInstance, IDC_ARROW));
                        MoveWindow(hwnd, 0, 0, 400, 100, 0);
                        MessageBox(hwnd, "已经成功截图", "提醒", MB_OK | MB_ICONINFORMATION );
                        if (!GetSaveFileName(&ofn))
                                return 0;
                        SaveBmp(hBitmap, szBuffer);
                        break;
                case 101:
                        if (!GetSaveFileName(&ofn))
                                return 0;
                        SaveBmp(hBitmap, szBuffer);
                        break;
                case 103:
                        Sleep(3000);
                                 SetCursor(LoadCursor(g_hInstance, IDC_WAIT));
                                 ShowWindow(hwnd, SW_HIDE);
                                 hBitmap = CaptureScreen(NULL);
                                 ShowWindow(hwnd, SW_SHOW);
                                 SetCursor(LoadCursor(g_hInstance, IDC_ARROW));
                                 MessageBox(hwnd, "已经成功截图", "提醒", MB_OK | MB_ICONINFORMATION);
                                 if (!GetSaveFileName(&ofn))
                                         return 0;
                                 SaveBmp(hBitmap, szBuffer);
                }
                return 0;
        case WM_PAINT:
                hdc = BeginPaint(hwnd, &ps);
                hdcMem = CreateCompatibleDC(hdc);
                SelectObject(hdcMem, hBitmap);
                GetObject(hBitmap, sizeof(BITMAP), &bitmap);
                cx = bitmap.bmWidth;
                cy = bitmap.bmHeight;
                BitBlt(hdcMem, 10, 10, cx, cy, hdc, 0, 0, SRCCOPY);
                EndPaint(hwnd, &ps);
                return 0;
        case WM_DESTROY:
                DeleteObject(hBitmap);
                PostQuitMessage(0);
                return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam); 
}

#ifndef CAPTUREBLT
#define CAPTUREBLT 0x40000000
#endif
HBITMAP CaptureScreen(LPRECT lpRect)//lpRect为NULL时表示全屏幕截图
{
        Sleep(1000);
        HDC      hdc, hdcMem;
        HBITMAP  hemfCopy;
        HWND     hwndScr;
        int      dstcx, dstcy;
        if (lpRect)
        {
                dstcx = lpRect->right - lpRect->left;
                dstcy = lpRect->bottom - lpRect->top;
        }
        else
        {
                dstcx = GetSystemMetrics(SM_CXSCREEN);
                dstcy = GetSystemMetrics(SM_CYSCREEN);
        }
        if (LockWindowUpdate(hwndScr = GetDesktopWindow()))
        {
                hdc = GetDCEx(hwndScr, NULL, DCX_CACHE | DCX_LOCKWINDOWUPDATE);
                hdcMem = CreateCompatibleDC(hdc);
                if (NULL == hdcMem)
                {
                        ReleaseDC(hwndScr, hdc);
                        LockWindowUpdate(NULL);
                        return NULL;
                }
                hemfCopy = CreateCompatibleBitmap(hdc, abs(dstcx), abs(dstcy));
                if (NULL == hemfCopy)
                {
                        DeleteDC(hdcMem);
                        ReleaseDC(hwndScr, hdc);
                        LockWindowUpdate(NULL);
                        return NULL;
                }
                SelectObject(hdcMem, hemfCopy);
                if (lpRect)
                        StretchBlt(hdcMem, 0, 0, abs(dstcx), abs(dstcy),
                        hdc, lpRect->left, lpRect->top, dstcx, dstcy, SRCCOPY | CAPTUREBLT);
                else
                        BitBlt(hdcMem, 0, 0, dstcx, dstcy,
                        hdc, 0, 0, SRCCOPY | CAPTUREBLT);
                DeleteDC(hdcMem);
                ReleaseDC(hwndScr, hdc);
                LockWindowUpdate(NULL);
                return hemfCopy;
        }
        return NULL;
}

BOOL SaveBmp(HBITMAP hBitmap, const char *FileName)
{
        HDC     hDC;
        //当前分辨率下每象素所占字节数       
        int     iBits;
        //位图中每象素所占字节数       
        WORD     wBitCount;
        //定义调色板大小,     位图中像素字节大小     ,位图文件大小     ,     写入文件字节数           
        DWORD     dwPaletteSize = 0, dwBmBitsSize = 0, dwDIBSize = 0, dwWritten = 0;
        //位图属性结构           
        BITMAP     Bitmap;
        //位图文件头结构       
        BITMAPFILEHEADER     bmfHdr;
        //位图信息头结构           
        BITMAPINFOHEADER     bi;
        //指向位图信息头结构               
        LPBITMAPINFOHEADER     lpbi;
        //定义文件,分配内存句柄,调色板句柄           
        HANDLE     fh, hDib, hPal, hOldPal = NULL;

        //计算位图文件每个像素所占字节数           
        hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
        iBits = GetDeviceCaps(hDC, BITSPIXEL) *GetDeviceCaps(hDC, PLANES);
        DeleteDC(hDC);
        if (iBits <= 1)
        {
                wBitCount = 1;
        }
        else if (iBits <= 4)
        {
                wBitCount = 4;
        }
        else if (iBits <= 8)
        {
                wBitCount = 8;
        }
        else
        {
                wBitCount = 24;
        }

        GetObject(hBitmap, sizeof(Bitmap), (LPSTR)&Bitmap);
        bi.biSize = sizeof(BITMAPINFOHEADER);
        bi.biWidth = Bitmap.bmWidth;
        bi.biHeight = Bitmap.bmHeight;
        bi.biPlanes = 1;
        bi.biBitCount = wBitCount;
        bi.biCompression = BI_RGB;
        bi.biSizeImage = 0;
        bi.biXPelsPerMeter = 0;
        bi.biYPelsPerMeter = 0;
        bi.biClrImportant = 0;
        bi.biClrUsed = 0;

        dwBmBitsSize = ((Bitmap.bmWidth     *     wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;

        //为位图内容分配内存           
        hDib = GlobalAlloc(GHND, dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
        lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
        *lpbi = bi;

        //     处理调色板               
        hPal = GetStockObject(DEFAULT_PALETTE);
        if (hPal)
        {
                hDC = GetDC(NULL);
                hOldPal = SelectPalette(hDC, (HPALETTE)hPal, FALSE);
                RealizePalette(hDC);
        }

        //     获取该调色板下新的像素值           
        GetDIBits(hDC,
                hBitmap,
                0,
                (UINT)Bitmap.bmHeight,
                (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize,
                (BITMAPINFO *)lpbi,
                DIB_RGB_COLORS);

        //恢复调色板               
        if (hOldPal)
        {
                SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
                RealizePalette(hDC);
                ReleaseDC(NULL, hDC);
        }

        //创建位图文件               
        fh = CreateFile(FileName,
                GENERIC_WRITE,
                0,
                NULL,
                CREATE_ALWAYS,
                FILE_ATTRIBUTE_NORMAL,
                NULL);/*     FILE_FLAG_SEQUENTIAL_SCAN,     NULL);  */

        if (fh == INVALID_HANDLE_VALUE)
        {
                return     FALSE;
        }

        //     设置位图文件头           
        bmfHdr.bfType = 0x4D42;     //     "BM"           
        dwDIBSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwPaletteSize + dwBmBitsSize;
        bmfHdr.bfSize = dwDIBSize;
        bmfHdr.bfReserved1 = 0;
        bmfHdr.bfReserved2 = 0;
        bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER)+dwPaletteSize;
        //     写入位图文件头           
        WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
        //     写入位图文件其余内容           
        WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);
        //清除               
        GlobalUnlock(hDib);
        GlobalFree(hDib);
        CloseHandle(fh);

        return     TRUE;
}
最激动人心的附件来啦!!!!!!!
截图工具.zip (88.46 KB, 下载次数: 36)
今天省下来3次上传机会,因为我是新鱼油~

好吧888888888

评分

参与人数 5荣誉 +25 鱼币 +25 贡献 +16 收起 理由
小甲鱼 + 5 + 5 + 3 热爱鱼C^_^
zlh + 5 + 5 + 5 感谢楼主无私奉献!
zzk176 + 5 + 5 + 3 这个必须赞
~风介~ + 5 + 5 + 5 支持楼主!
小人 + 5 + 5 热爱鱼C^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2016-6-19 20:13:41 | 显示全部楼层
说一下,保存时文件名要加上.bmp
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-6-19 21:12:06 | 显示全部楼层
题目错了,应该是”SDK实现简单截屏功能“才对!@小甲鱼 @兰陵月
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-6-19 21:13:22 | 显示全部楼层
~风介~ 发表于 2016-6-19 21:12
题目错了,应该是”SDK实现简单截屏功能“才对!@小甲鱼 @兰陵月

这叫VC/VC++
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-6-19 21:15:54 | 显示全部楼层

没学过VC/VC++
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-6-19 21:30:34 | 显示全部楼层

好吧-_-||
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-6-19 22:12:19 | 显示全部楼层
顶一下吧!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-6-20 09:35:41 | 显示全部楼层
~风介~ 发表于 2016-6-19 21:12
题目错了,应该是”SDK实现简单截屏功能“才对!@小甲鱼 @兰陵月

已经好久没弄C了,以后温故知新了再献丑,哈哈~

我现在全身心都在汇编~~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-6-20 12:00:48 | 显示全部楼层
兰陵月 发表于 2016-6-20 09:35
已经好久没弄C了,以后温故知新了再献丑,哈哈~

我现在全身心都在汇编~~

是不是反编译软件看不懂啊?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-6-20 18:07:09 | 显示全部楼层
666,我以前也想弄一个,没弄成,要把代码好好的研究一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-6-20 18:57:31 | 显示全部楼层
求版主们加精
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-6-20 21:57:36 | 显示全部楼层
自己顶一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-6-21 01:08:34 | 显示全部楼层
不错不错
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-6-21 11:21:23 | 显示全部楼层
无符号整形 发表于 2016-6-20 12:00
是不是反编译软件看不懂啊?

不是,只是为了更加灵活运用windows32汇编,然后再研究下64汇编~达到较为熟练的程序~

当然最终目的为了逆向~

C肯定还是要搞的~只是暂时放下~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-6-21 11:25:01 | 显示全部楼层
8086汇编下,当前屏幕显示的是0b800以后的字节~

windows下,C下肯定是有类似的空间保存屏幕的二进制内容~

你这个截屏是不是先保存二进制内容,再显示出来~类似这样的原理?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-6-21 17:55:57 | 显示全部楼层
兰陵月 发表于 2016-6-21 11:25
8086汇编下,当前屏幕显示的是0b800以后的字节~

windows下,C下肯定是有类似的空间保存屏幕的二进制内容 ...

没学过8086汇编,但是可以告诉你:
先截图
然后保存到文件
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-6-21 19:38:40 | 显示全部楼层
无符号整形 发表于 2016-6-21 17:55
没学过8086汇编,但是可以告诉你:
先截图
然后保存到文件

我就是说的截图的过程,图也是二进制数据组成的,截图就是把排列好的二进制数据保存下来,然后再显示出来~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-6-21 20:51:55 | 显示全部楼层
兰陵月 发表于 2016-6-21 19:38
我就是说的截图的过程,图也是二进制数据组成的,截图就是把排列好的二进制数据保存下来,然后再显示出来 ...

嗯嗯是的⊙▽⊙
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-6-22 11:50:59 | 显示全部楼层
大家对代码有什么问题可以回复哦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-6-24 11:53:27 | 显示全部楼层
顶一下因为没人
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-22 22:48

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表