Create project "Grabby".
git-svn-id: svn://vcs.sdm.2ki.xyz/Grabby/trunk@9 27729192-006e-004d-b9b5-06fbd0ef7001
This commit is contained in:
commit
585e61636a
352
Bitmap.c
Normal file
352
Bitmap.c
Normal file
|
@ -0,0 +1,352 @@
|
|||
#include "stdafx.h"
|
||||
#include "Bitmap.h"
|
||||
|
||||
void DeleteScreen(Screen *);
|
||||
|
||||
Screen *
|
||||
CreateScreen(void)
|
||||
{
|
||||
Screen *scrn = GlobalAlloc(GPTR, sizeof(Screen));
|
||||
RECT rectScreen = { 0 };
|
||||
|
||||
if (!scrn) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
scrn->hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL);
|
||||
scrn->hdcBitmap = CreateCompatibleDC(scrn->hdcScreen);
|
||||
|
||||
rectScreen.right = GetDeviceCaps(scrn->hdcScreen, HORZRES);
|
||||
rectScreen.bottom = GetDeviceCaps(scrn->hdcScreen, VERTRES);
|
||||
|
||||
scrn->hScreenRgn = CreateRectRgnIndirect(&rectScreen);
|
||||
if (!scrn->hScreenRgn) {
|
||||
// Store the error to be bubbled up
|
||||
DWORD err = GetLastError();
|
||||
DeleteScreen(scrn);
|
||||
SetLastError(err);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return scrn;
|
||||
}
|
||||
|
||||
void
|
||||
DeleteScreen(Screen *scrn)
|
||||
{
|
||||
if (scrn) {
|
||||
if (scrn->hScreenRgn) DeleteObject((HGDIOBJ) scrn->hScreenRgn);
|
||||
if (scrn->hdcBitmap) DeleteDC(scrn->hdcBitmap);
|
||||
if (scrn->hdcScreen) DeleteDC(scrn->hdcScreen);
|
||||
|
||||
GlobalFree(scrn);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#include <pshpack1.h>
|
||||
typedef struct _FULLBMPHDR {
|
||||
BITMAPFILEHEADER file;
|
||||
BITMAPINFOHEADER info;
|
||||
} FULLBMPHDR, *PFULLBMPHDR;
|
||||
#include <poppack.h>
|
||||
|
||||
PFULLBMPHDR
|
||||
GenerateBitmapInfo(Screen *scrn,
|
||||
BITMAP *bmp)
|
||||
{
|
||||
PFULLBMPHDR pBmpHdr = HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
sizeof(struct _FULLBMPHDR));
|
||||
RECT rcScrn = {0};
|
||||
WORD cClrBits = (WORD)(bmp->bmPlanes * bmp->bmBitsPixel);
|
||||
DWORD hdrSize;
|
||||
|
||||
if (!pBmpHdr) return NULL;
|
||||
|
||||
if (!GetRgnBox(scrn->hScreenRgn, &rcScrn)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cClrBits <= 16) {
|
||||
cClrBits = 16;
|
||||
} else {
|
||||
cClrBits = 32;
|
||||
}
|
||||
|
||||
pBmpHdr->info.biSize = sizeof(BITMAPINFOHEADER);
|
||||
pBmpHdr->info.biWidth = bmp->bmWidth;
|
||||
pBmpHdr->info.biHeight = bmp->bmHeight;
|
||||
pBmpHdr->info.biPlanes = bmp->bmPlanes;
|
||||
pBmpHdr->info.biBitCount = cClrBits;
|
||||
pBmpHdr->info.biCompression = BI_RGB;
|
||||
// According to MSDN docs, this alignment to WORD boundaries is
|
||||
// required for Win9x GDI.
|
||||
pBmpHdr->info.biSizeImage = (((bmp->bmWidth * cClrBits + 31) & ~31) >> 3)
|
||||
* bmp->bmHeight;
|
||||
|
||||
pBmpHdr->file.bfType = 0x4d42; // "BM"
|
||||
// actual bits offset: file header + info header + colors used
|
||||
hdrSize = (DWORD) (sizeof(BITMAPFILEHEADER) +
|
||||
pBmpHdr->info.biSize +
|
||||
((cClrBits >= 16) ? 0 : (pBmpHdr->info.biClrUsed *
|
||||
sizeof(RGBQUAD))));
|
||||
// file size is header size (offset above) + bits size
|
||||
pBmpHdr->file.bfSize = hdrSize + pBmpHdr->info.biSizeImage;
|
||||
pBmpHdr->file.bfOffBits = hdrSize;
|
||||
|
||||
return pBmpHdr;
|
||||
}
|
||||
|
||||
int
|
||||
SnapScreen(Screen *scrn)
|
||||
{
|
||||
RECT rcScreen = {0};
|
||||
int iScrWidth,
|
||||
iScrHeight;
|
||||
if (!scrn) return FALSE;
|
||||
|
||||
// Don't make a new hBitmap if we have one
|
||||
if (scrn->hBitmap) return TRUE;
|
||||
|
||||
GetRgnBox(scrn->hScreenRgn, &rcScreen);
|
||||
|
||||
iScrWidth = rcScreen.right - rcScreen.left;
|
||||
iScrHeight = rcScreen.bottom - rcScreen.top;
|
||||
|
||||
scrn->hBitmap = CreateCompatibleBitmap(scrn->hdcScreen,
|
||||
iScrWidth,
|
||||
iScrHeight);
|
||||
if (!scrn->hBitmap) return FALSE;
|
||||
|
||||
scrn->hOldObj = SelectObject(scrn->hdcBitmap, scrn->hBitmap);
|
||||
if (!scrn->hOldObj) {
|
||||
DWORD err = GetLastError();
|
||||
DeleteObject(scrn->hBitmap);
|
||||
scrn->hBitmap = NULL;
|
||||
SetLastError(err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!BitBlt(scrn->hdcBitmap,
|
||||
0, 0,
|
||||
iScrWidth,
|
||||
iScrHeight,
|
||||
scrn->hdcScreen,
|
||||
rcScreen.left, rcScreen.top,
|
||||
SRCCOPY))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
SelectObject(scrn->hdcBitmap, scrn->hOldObj);
|
||||
DeleteObject(scrn->hBitmap);
|
||||
scrn->hBitmap = NULL;
|
||||
SetLastError(err);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
WriteRegionToFile(Screen *scrn,
|
||||
RECT *rgn,
|
||||
LPTSTR fname)
|
||||
{
|
||||
BITMAP bmp = {0}; // hBitmap's metadata
|
||||
HANDLE hOutFile = NULL; // Output .bmp
|
||||
LPBYTE lpBits = NULL; // Actual bitmap bits
|
||||
|
||||
HDC hdcRgn = NULL; // HDC for defined region
|
||||
HBITMAP hRgnBitmap = NULL; // Bitmap of defined region
|
||||
HGDIOBJ hOldObj = NULL; // Old bitmap, if any
|
||||
PFULLBMPHDR pHdr = NULL; // Full bitmap header
|
||||
PBITMAPINFO pbmi = NULL; // BMI header, in case bits <= 8
|
||||
|
||||
WORD cClrBits = 0; // How many bits per pixel
|
||||
|
||||
BOOL hasErr = FALSE; // If something went wrong, set this
|
||||
DWORD err = 0, // Used to store LastError
|
||||
dwTmp = 0; // Used for written bytes storage
|
||||
|
||||
if (!scrn || (!rgn || !fname)) {
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!RectInRegion(scrn->hScreenRgn, rgn)) {
|
||||
// TODO: is there a better error we can set here?
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Overlay already grabs the screen, so don't trample over it
|
||||
if (!scrn->hBitmap && !SnapScreen(scrn))
|
||||
{
|
||||
hasErr = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
hdcRgn = CreateCompatibleDC(scrn->hdcScreen);
|
||||
if (!hdcRgn) {
|
||||
hasErr = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Create a new bitmap for the specific region
|
||||
hRgnBitmap = CreateCompatibleBitmap(scrn->hdcScreen,
|
||||
rgn->right - rgn->left,
|
||||
rgn->bottom - rgn->top);
|
||||
if (!hRgnBitmap) {
|
||||
hasErr = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
if (!GetObject(hRgnBitmap, sizeof(BITMAP), &bmp)) {
|
||||
hasErr = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
hOldObj = SelectObject(hdcRgn, hRgnBitmap);
|
||||
if (!hOldObj) {
|
||||
hasErr = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!BitBlt(
|
||||
hdcRgn,
|
||||
0, 0,
|
||||
rgn->right - rgn->left,
|
||||
rgn->bottom - rgn->top,
|
||||
scrn->hdcBitmap,
|
||||
rgn->left, rgn->top,
|
||||
SRCCOPY))
|
||||
{
|
||||
hasErr = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
pHdr = GenerateBitmapInfo(scrn,
|
||||
&bmp);
|
||||
if (!pHdr) {
|
||||
hasErr = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
lpBits = HeapAlloc(GetProcessHeap(),
|
||||
0,
|
||||
pHdr->info.biSizeImage);
|
||||
if (!lpBits) {
|
||||
hasErr = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (pHdr->info.biBitCount <= 8) {
|
||||
pbmi = HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
sizeof(BITMAPINFOHEADER) +
|
||||
(pHdr->info.biClrUsed * sizeof(RGBQUAD)));
|
||||
if (!pbmi) {
|
||||
hasErr = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
CopyMemory(&pbmi->bmiHeader, &pHdr->info, sizeof(BITMAPINFOHEADER));
|
||||
} else {
|
||||
// For all other bit sizes, we don't care about the color
|
||||
// table. Just use the info header directly.
|
||||
// (Yes this is pretty shady. Don't worry about it)
|
||||
pbmi = (PBITMAPINFO) &pHdr->info;
|
||||
}
|
||||
|
||||
if (!GetDIBits(scrn->hdcBitmap,
|
||||
hRgnBitmap,
|
||||
0,
|
||||
(WORD) pHdr->info.biHeight,
|
||||
lpBits,
|
||||
pbmi,
|
||||
DIB_RGB_COLORS))
|
||||
{
|
||||
hasErr = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Create and write to the output file
|
||||
|
||||
hOutFile = CreateFile(fname,
|
||||
GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (hOutFile == INVALID_HANDLE_VALUE) {
|
||||
hasErr = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// First, write the header
|
||||
if (!WriteFile(hOutFile, pHdr, sizeof(FULLBMPHDR), &dwTmp, NULL)) {
|
||||
hasErr = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Assuming we're only using 16- or 32-bit BMPs, we should never
|
||||
// need to write a color table. But since this could easily be
|
||||
// modified to support smaller bit widths (i.e., 256 or less),
|
||||
// let's make sure such cases don't crash.
|
||||
if (pHdr->info.biBitCount <= 8) {
|
||||
if (!WriteFile(hOutFile,
|
||||
pbmi,
|
||||
pbmi->bmiHeader.biClrUsed * sizeof(RGBQUAD),
|
||||
&dwTmp,
|
||||
NULL))
|
||||
{
|
||||
hasErr = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
// And last but not least, the pixels
|
||||
if (!WriteFile(hOutFile, lpBits, pHdr->info.biSizeImage, &dwTmp, NULL)) {
|
||||
hasErr = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
// make sure to grab the error before we start freeing everything
|
||||
if (hasErr) {
|
||||
err = GetLastError();
|
||||
}
|
||||
|
||||
if (hOutFile) {
|
||||
CloseHandle(hOutFile);
|
||||
if (hasErr) {
|
||||
// Since it's probably busted, try to delete it too
|
||||
DeleteFile(fname);
|
||||
}
|
||||
}
|
||||
|
||||
if (lpBits) HeapFree(GetProcessHeap(), 0, lpBits);
|
||||
|
||||
// In case our bits are <= 8, pbmi will be an actual heap-alloc'd
|
||||
// pointer. Let's make sure to handle that.
|
||||
if (pbmi && pbmi != (PBITMAPINFO) &pHdr->info) HeapFree(GetProcessHeap(), 0, pbmi);
|
||||
|
||||
if (pHdr) HeapFree(GetProcessHeap(), 0, pHdr);
|
||||
|
||||
if (scrn->hOldObj) SelectObject(scrn->hdcBitmap, scrn->hOldObj);
|
||||
if (hOldObj) SelectObject(hdcRgn, hOldObj);
|
||||
if (hRgnBitmap) DeleteObject(hRgnBitmap);
|
||||
if (scrn->hBitmap) DeleteObject(scrn->hBitmap);
|
||||
|
||||
if (hdcRgn) DeleteDC(hdcRgn);
|
||||
|
||||
if (hasErr) {
|
||||
SetLastError(err);
|
||||
}
|
||||
|
||||
return hasErr ? -1 : 0;
|
||||
}
|
18
Bitmap.h
Normal file
18
Bitmap.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
typedef struct _Screen {
|
||||
HDC hdcScreen;
|
||||
HDC hdcBitmap;
|
||||
HRGN hScreenRgn;
|
||||
HBITMAP hBitmap;
|
||||
HGDIOBJ hOldObj;
|
||||
} Screen;
|
||||
|
||||
// Create a Screen struct.
|
||||
Screen *CreateScreen(void);
|
||||
// Write a screen region to the given filename.
|
||||
int WriteRegionToFile(Screen *, RECT *, LPTSTR);
|
||||
// Commit a "screenshot" of the screen to scrn->hBitmap
|
||||
int SnapScreen(Screen *);
|
94
Grabby.c
Normal file
94
Grabby.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
// Grabby.cpp : Defines the entry point for the application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Bitmap.h"
|
||||
#include "Overlay.h"
|
||||
#include "Grabby.h"
|
||||
|
||||
/**
|
||||
* Print an error with a given context before bailing out
|
||||
*/
|
||||
void Die(LPTSTR lpContextMsg)
|
||||
{
|
||||
LPCTSTR lpszFmt = "%s: %s";
|
||||
int iFullLen;
|
||||
LPTSTR lpszError = NULL,
|
||||
lpszFullMsg = NULL;
|
||||
|
||||
// The whole point of this is to print an actual message, so get the
|
||||
// actual message
|
||||
if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
0,
|
||||
(LPTSTR) &lpszError,
|
||||
0,
|
||||
NULL))
|
||||
{
|
||||
if (lpszError != NULL) LocalFree(lpszError);
|
||||
lpszError = _T("unknown error");
|
||||
}
|
||||
|
||||
iFullLen = _sctprintf(lpszFmt, lpContextMsg, lpszError);
|
||||
lpszFullMsg = (LPTSTR) LocalAlloc(LPTR, sizeof(TCHAR) * (iFullLen + 1));
|
||||
|
||||
if (lpszFullMsg == NULL) {
|
||||
// I'm honestly gonna guess if we get here, we're out of memory.
|
||||
// So let's print what we have and bail
|
||||
MessageBox(NULL,
|
||||
lpContextMsg,
|
||||
_T("Catastrophic Error"),
|
||||
MB_OK | MB_ICONERROR);
|
||||
} else {
|
||||
_sntprintf(lpszFullMsg, iFullLen, lpszFmt, lpContextMsg, lpszError);
|
||||
MessageBox(NULL,
|
||||
lpszFullMsg,
|
||||
_T("Fatal Error"),
|
||||
MB_OK | MB_ICONERROR);
|
||||
}
|
||||
|
||||
// TODO: should we still be nice and free memory here?
|
||||
ExitProcess(1);
|
||||
}
|
||||
|
||||
int APIENTRY _tWinMain(HINSTANCE hInstance,
|
||||
HINSTANCE hPrevInstance,
|
||||
LPTSTR lpCmdLine,
|
||||
int nCmdShow)
|
||||
{
|
||||
RECT capRegion = {0};
|
||||
Screen *scrn = CreateScreen();
|
||||
|
||||
if (!scrn) {
|
||||
Die("Couldn't get screen information");
|
||||
}
|
||||
|
||||
switch (CreateOverlay(hInstance, scrn)) {
|
||||
case -1:
|
||||
Die("Couldn't create overlay window");
|
||||
break;
|
||||
case 0:
|
||||
/* Do nothing */
|
||||
break;
|
||||
case 1:
|
||||
// User requested we cancel out, so do that
|
||||
return 0;
|
||||
}
|
||||
|
||||
GetChosenRect(&capRegion);
|
||||
|
||||
|
||||
if (WriteRegionToFile(scrn, &capRegion, _T("test.bmp")) == -1) {
|
||||
Die("Couldn't grab region of the screen");
|
||||
}
|
||||
|
||||
MessageBox(NULL,
|
||||
_T("Successfully grabbed a part of the screen!"),
|
||||
_T("\\o/"),
|
||||
MB_OK | MB_ICONINFORMATION);
|
||||
|
||||
return 0;
|
||||
}
|
5
Grabby.h
Normal file
5
Grabby.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
void Die(LPTSTR);
|
BIN
Grabby.ico
Normal file
BIN
Grabby.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
128
Grabby.rc
Normal file
128
Grabby.rc
Normal file
|
@ -0,0 +1,128 @@
|
|||
//Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#define APSTUDIO_HIDDEN_SYMBOLS
|
||||
#include "windows.h"
|
||||
#undef APSTUDIO_HIDDEN_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
|
||||
LANGUAGE 17, 1
|
||||
#pragma code_page(932)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
|
||||
IDI_GRABBY ICON "Grabby.ico"
|
||||
IDI_SMALL ICON "small.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Menu
|
||||
//
|
||||
|
||||
IDC_GRABBY MENU
|
||||
BEGIN
|
||||
POPUP "&File"
|
||||
BEGIN
|
||||
MENUITEM "E&xit", IDM_EXIT
|
||||
END
|
||||
POPUP "&Help"
|
||||
BEGIN
|
||||
MENUITEM "&About ...", IDM_ABOUT
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Accelerator
|
||||
//
|
||||
|
||||
IDC_GRABBY ACCELERATORS
|
||||
BEGIN
|
||||
"?", IDM_ABOUT, ASCII, ALT
|
||||
"/", IDM_ABOUT, ASCII, ALT
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_ABOUTBOX DIALOG 22, 17, 230, 75
|
||||
STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "About"
|
||||
FONT 9, "System"
|
||||
BEGIN
|
||||
ICON IDI_GRABBY,IDC_MYICON,14,9,16,16
|
||||
LTEXT "Grabby Version 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX
|
||||
LTEXT "Copyright (C) 2024",IDC_STATIC,49,20,119,8
|
||||
DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
|
||||
END
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"#include ""windows.h""\r\n"
|
||||
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDC_GRABBY "GRABBY"
|
||||
IDS_APP_TITLE "Grabby"
|
||||
END
|
||||
|
||||
#endif
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
21
Grabby.sln
Normal file
21
Grabby.sln
Normal file
|
@ -0,0 +1,21 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Grabby", "Grabby.vcproj", "{700E5DD7-DD00-46D9-92DF-2C132940F53D}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
Release = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{700E5DD7-DD00-46D9-92DF-2C132940F53D}.Debug.ActiveCfg = Debug|Win32
|
||||
{700E5DD7-DD00-46D9-92DF-2C132940F53D}.Debug.Build.0 = Debug|Win32
|
||||
{700E5DD7-DD00-46D9-92DF-2C132940F53D}.Release.ActiveCfg = Release|Win32
|
||||
{700E5DD7-DD00-46D9-92DF-2C132940F53D}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
172
Grabby.vcproj
Normal file
172
Grabby.vcproj
Normal file
|
@ -0,0 +1,172 @@
|
|||
<?xml version="1.0" encoding="shift_jis"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="Grabby"
|
||||
ProjectGUID="{700E5DD7-DD00-46D9-92DF-2C132940F53D}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="5"
|
||||
UsePrecompiledHeader="3"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="1"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/Grabby.exe"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/Grabby.pdb"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
|
||||
RuntimeLibrary="4"
|
||||
UsePrecompiledHeader="3"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/Grabby.exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath=".\Bitmap.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Grabby.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Overlay.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.c">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
||||
<File
|
||||
RelativePath=".\Bitmap.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Grabby.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Resource.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
|
||||
<File
|
||||
RelativePath=".\Grabby.ico">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Grabby.rc">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\small.ico">
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\ReadMe.txt">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
225
Overlay.c
Normal file
225
Overlay.c
Normal file
|
@ -0,0 +1,225 @@
|
|||
#include "stdafx.h"
|
||||
#include "Bitmap.h"
|
||||
|
||||
LRESULT CALLBACK OverlayWndProc(HWND, UINT, WPARAM, LPARAM);
|
||||
|
||||
#define OVERLAY_CLASS _T("GrabbyOverlay")
|
||||
#define OVERLAY_TITLE _T("Grabby Overlay")
|
||||
|
||||
// Static function to store and retrieve the overlay-chosen rect.
|
||||
static void
|
||||
SetGetRect(BOOL set, RECT *r)
|
||||
{
|
||||
static RECT rcMain = {0};
|
||||
if (r) {
|
||||
if (set) {
|
||||
CopyMemory(&rcMain, r, sizeof(RECT));
|
||||
} else {
|
||||
CopyMemory(r, &rcMain, sizeof(RECT));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
GetChosenRect(RECT *rcOut)
|
||||
{
|
||||
SetGetRect(FALSE, rcOut);
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
CreateOverlay(HINSTANCE hInstance,
|
||||
Screen *scrn)
|
||||
{
|
||||
HWND hWnd = NULL;
|
||||
RECT rcScreen = {0};
|
||||
MSG msg = {0};
|
||||
BOOL bRet;
|
||||
WNDCLASSEX wcClass = {
|
||||
sizeof(WNDCLASSEX),
|
||||
CS_HREDRAW | CS_VREDRAW,
|
||||
OverlayWndProc,
|
||||
0,
|
||||
0,
|
||||
hInstance,
|
||||
LoadIcon(NULL, IDI_APPLICATION),
|
||||
LoadCursor(NULL, IDC_CROSS),
|
||||
(HBRUSH)( COLOR_WINDOW + 1 ),
|
||||
OVERLAY_TITLE,
|
||||
OVERLAY_CLASS,
|
||||
NULL
|
||||
};
|
||||
|
||||
if (!RegisterClassEx(&wcClass)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!GetRgnBox(scrn->hScreenRgn, &rcScreen)) {
|
||||
UnregisterClass(OVERLAY_CLASS, hInstance);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hWnd = CreateWindowEx(
|
||||
WS_EX_TOPMOST,
|
||||
OVERLAY_CLASS,
|
||||
OVERLAY_TITLE,
|
||||
WS_VISIBLE | WS_POPUP,
|
||||
rcScreen.left,
|
||||
rcScreen.top,
|
||||
rcScreen.right - rcScreen.left,
|
||||
rcScreen.bottom - rcScreen.top,
|
||||
NULL,
|
||||
NULL,
|
||||
hInstance,
|
||||
scrn);
|
||||
|
||||
if (!hWnd) {
|
||||
UnregisterClass(OVERLAY_CLASS, hInstance);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ShowWindow(hWnd, SW_SHOWNORMAL);
|
||||
|
||||
while ((bRet = GetMessage(&msg, hWnd, 0, 0)) != 0) {
|
||||
if (bRet == -1) {
|
||||
// TODO: error handling
|
||||
break;
|
||||
} else {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (hWnd) DestroyWindow(hWnd);
|
||||
UnregisterClass(OVERLAY_CLASS, hInstance);
|
||||
|
||||
return (int)msg.wParam;
|
||||
}
|
||||
|
||||
// Left, Top, Right, Bottom
|
||||
#define POINT2RECT(a,b) { \
|
||||
min(a.x, b.x), \
|
||||
min(a.y, b.y), \
|
||||
max(a.x, b.x), \
|
||||
max(a.y, b.y) \
|
||||
}
|
||||
|
||||
LRESULT CALLBACK
|
||||
OverlayWndProc(HWND hWnd,
|
||||
UINT uMsg,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
HDC hDC = NULL;
|
||||
PAINTSTRUCT ps = {0};
|
||||
static POINTS ptStart = {0}, // Starting drag point
|
||||
ptCur = {0}; // Current/end drag point
|
||||
static BOOL isDrag = FALSE; // Are we mid-drag?
|
||||
static Screen *scrn = NULL; // Screen data
|
||||
static RECT rcScreen = {0};
|
||||
static HGDIOBJ hOldObj = NULL;
|
||||
|
||||
switch (uMsg) {
|
||||
case WM_CREATE:
|
||||
{
|
||||
HDC dcWnd = GetDC(hWnd);
|
||||
// Get the Screen object passed in from CreateWindowEx
|
||||
HBITMAP hOldBmp = NULL;
|
||||
LPCREATESTRUCT csCreate = (LPCREATESTRUCT)lParam;
|
||||
if (csCreate && csCreate->lpCreateParams) {
|
||||
scrn = (Screen *)csCreate->lpCreateParams;
|
||||
if (!scrn) {
|
||||
// uhhhhhhhhh
|
||||
MessageBox(hWnd,
|
||||
_T("Couldn't get screen info for mysterious reasons !?"),
|
||||
_T("Fatal Error"),
|
||||
MB_OK | MB_ICONERROR);
|
||||
PostQuitMessage(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
GetRgnBox(scrn->hScreenRgn, &rcScreen);
|
||||
|
||||
if (!SnapScreen(scrn)) {
|
||||
MessageBox(hWnd,
|
||||
_T("Couldn't store screen data !!"),
|
||||
_T("Fatal Error"),
|
||||
MB_OK | MB_ICONERROR);
|
||||
PostQuitMessage(1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* PASSTHRU */
|
||||
case WM_PAINT:
|
||||
hDC = BeginPaint(hWnd, &ps);
|
||||
|
||||
if (scrn->hBitmap) {
|
||||
// Draw the "background"
|
||||
if (!BitBlt(hDC,
|
||||
ps.rcPaint.left,
|
||||
ps.rcPaint.top,
|
||||
ps.rcPaint.right - ps.rcPaint.left,
|
||||
ps.rcPaint.bottom - ps.rcPaint.top,
|
||||
scrn->hdcBitmap,
|
||||
rcScreen.left + ps.rcPaint.left,
|
||||
rcScreen.top + ps.rcPaint.top,
|
||||
SRCCOPY))
|
||||
{
|
||||
// walk it off, I guess...
|
||||
OutputDebugString(_T("Failed to blit background to DC..."));
|
||||
}
|
||||
}
|
||||
|
||||
if (isDrag && hDC) {
|
||||
RECT rcOuter = POINT2RECT(ptStart, ptCur);
|
||||
DrawFocusRect(hDC, &rcOuter);
|
||||
}
|
||||
|
||||
EndPaint(hWnd, &ps);
|
||||
break;
|
||||
case WM_MOUSEMOVE:
|
||||
if (isDrag && (wParam & MK_LBUTTON)) {
|
||||
POINTS ptPrev = ptCur;
|
||||
ptCur = MAKEPOINTS(lParam);
|
||||
if ((ptCur.x != ptStart.x) &&
|
||||
(ptCur.y != ptStart.y))
|
||||
{
|
||||
RECT rcPrevDmg = POINT2RECT(ptStart, ptPrev);
|
||||
// InvalidateRect(hWnd, &rcCurDmg, TRUE);
|
||||
InvalidateRect(hWnd, &rcPrevDmg, TRUE);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case WM_LBUTTONDOWN:
|
||||
if (!isDrag) {
|
||||
// Start the drag operation and set the origin
|
||||
ptStart = ptCur = MAKEPOINTS(lParam);
|
||||
isDrag = TRUE;
|
||||
}
|
||||
break;
|
||||
case WM_LBUTTONUP:
|
||||
if (isDrag) {
|
||||
// Done dragging, store the rect and get out of here
|
||||
RECT rcFinal = POINT2RECT(ptStart, ptCur);
|
||||
|
||||
SetGetRect(TRUE, &rcFinal);
|
||||
isDrag = FALSE;
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
break;
|
||||
case WM_KEYUP:
|
||||
// TODO: Escape
|
||||
break;
|
||||
case WM_RBUTTONUP:
|
||||
// We treat right click as Escape
|
||||
PostQuitMessage(1);
|
||||
break;
|
||||
default:
|
||||
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
9
Overlay.h
Normal file
9
Overlay.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "Bitmap.h"
|
||||
|
||||
// Gets a RECT representing the screen region the user wants.
|
||||
void GetChosenRect(RECT *);
|
||||
|
||||
// Creates the overlay window.
|
||||
int CreateOverlay(HINSTANCE, Screen *);
|
53
ReadMe.txt
Normal file
53
ReadMe.txt
Normal file
|
@ -0,0 +1,53 @@
|
|||
========================================================================
|
||||
WIN32 APPLICATION : Grabby Project Overview
|
||||
========================================================================
|
||||
|
||||
AppWizard has created this Grabby application for you.
|
||||
This file contains a summary of what you will find in each of the files that
|
||||
make up your Grabby application.
|
||||
|
||||
|
||||
Grabby.vcproj
|
||||
This is the main project file for VC++ projects generated using an Application Wizard.
|
||||
It contains information about the version of Visual C++ that generated the file, and
|
||||
information about the platforms, configurations, and project features selected with the
|
||||
Application Wizard.
|
||||
|
||||
Grabby.cpp
|
||||
This is the main application source file.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
AppWizard has created the following resources:
|
||||
|
||||
Grabby.rc
|
||||
This is a listing of all of the Microsoft Windows resources that the
|
||||
program uses. It includes the icons, bitmaps, and cursors that are stored
|
||||
in the RES subdirectory. This file can be directly edited in Microsoft
|
||||
Visual C++.
|
||||
|
||||
Resource.h
|
||||
This is the standard header file, which defines new resource IDs.
|
||||
Microsoft Visual C++ reads and updates this file.
|
||||
Grabby.ico
|
||||
This is an icon file, which is used as the application's icon (32x32).
|
||||
This icon is included by the main resource file Grabby.rc.
|
||||
|
||||
small.ico
|
||||
This is an icon file, which contains a smaller version (16x16)
|
||||
of the application's icon. This icon is included by the main resource
|
||||
file Grabby.rc.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Other standard files:
|
||||
|
||||
StdAfx.h, StdAfx.cpp
|
||||
These files are used to build a precompiled header (PCH) file
|
||||
named Grabby.pch and a precompiled types file named StdAfx.obj.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Other notes:
|
||||
|
||||
AppWizard uses "TODO:" comments to indicate parts of the source code you
|
||||
should add to or customize.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
29
Resource.h
Normal file
29
Resource.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by Grabby.rc
|
||||
//
|
||||
|
||||
#define IDS_APP_TITLE 103
|
||||
|
||||
#define IDR_MAINFRAME 128
|
||||
#define IDD_GRABBY_DIALOG 102
|
||||
#define IDD_ABOUTBOX 103
|
||||
#define IDM_ABOUT 104
|
||||
#define IDM_EXIT 105
|
||||
#define IDI_GRABBY 107
|
||||
#define IDI_SMALL 108
|
||||
#define IDC_GRABBY 109
|
||||
#define IDC_MYICON 2
|
||||
#define IDC_STATIC -1
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
#define _APS_NO_MFC 130
|
||||
#define _APS_NEXT_RESOURCE_VALUE 129
|
||||
#define _APS_NEXT_COMMAND_VALUE 32771
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 110
|
||||
#endif
|
||||
#endif
|
8
stdafx.c
Normal file
8
stdafx.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// Grabby.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
19
stdafx.h
Normal file
19
stdafx.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
// Windows Header Files:
|
||||
#include <windows.h>
|
||||
// C RunTime Header Files
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <memory.h>
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
Loading…
Reference in a new issue