mirror of https://github.com/GNOME/gimp.git
plug-ins: convert win-snap to screenshot
works as win-snap, lots of optimizing work to be done.
This commit is contained in:
parent
ad25307a3b
commit
ed80db30c9
|
@ -10,11 +10,7 @@ libgimpmath = $(top_builddir)/libgimpmath/libgimpmath-$(GIMP_API_VERSION).la
|
|||
|
||||
if OS_WIN32
|
||||
mwindows = -mwindows
|
||||
endif
|
||||
|
||||
if HAVE_WINDRES
|
||||
include $(top_srcdir)/build/windows/gimprc-plug-ins.rule
|
||||
screenshot_RC = screenshot.rc.o
|
||||
screenshot_RC = screenshot-win32res.o
|
||||
endif
|
||||
|
||||
AM_LDFLAGS = $(mwindows)
|
||||
|
@ -57,5 +53,18 @@ screenshot_SOURCES = \
|
|||
screenshot-osx.h \
|
||||
screenshot-x11.c \
|
||||
screenshot-x11.h \
|
||||
screenshot-win32.rc \
|
||||
screenshot-win32.c \
|
||||
screenshot-win32.h
|
||||
|
||||
if OS_WIN32
|
||||
EXTRA_DIST = \
|
||||
resource.h \
|
||||
select.cur \
|
||||
small.ico \
|
||||
screenshot-win32.ico \
|
||||
screenshot-win32.rc
|
||||
|
||||
screenshot-win32res.o: screenshot-win32.rc select.cur small.ico screenshot-win32.ico
|
||||
$(WINDRES) $(srcdir)/screenshot-win32.rc screenshot-win32res.o
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/* {{NO_DEPENDENCIES}}
|
||||
Microsoft Developer Studio generated include file.
|
||||
Used by snappy.rc
|
||||
*/
|
||||
#define IDM_CAPTURE 100
|
||||
#define IDM_EXIT 101
|
||||
|
||||
#define IDC_SELECT 102
|
||||
#define IDD_SELECT 103
|
||||
#define IDC_TEXT 1000
|
||||
#define IDC_GROUP 1001
|
||||
#define IDM_CAPTUREFULL 40003
|
||||
#define IDM_HOOK 40004
|
||||
#define IDM_UNHOOK 40005
|
||||
|
||||
/* Next default values for new objects */
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NO_MFC 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 104
|
||||
#define _APS_NEXT_COMMAND_VALUE 40006
|
||||
#define _APS_NEXT_CONTROL_VALUE 1002
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
|
@ -36,12 +36,100 @@
|
|||
|
||||
#include "screenshot.h"
|
||||
#include "screenshot-win32.h"
|
||||
#include "resource.h"
|
||||
|
||||
#include "libgimp/stdplugins-intl.h"
|
||||
|
||||
/*
|
||||
* Application definitions
|
||||
*/
|
||||
#define SELECT_FRAME 0
|
||||
#define SELECT_CLIENT 1
|
||||
#define SELECT_WINDOW 2
|
||||
|
||||
#define SHOW_WINDOW FALSE
|
||||
#define APP_NAME "plug_in_screenshot_win"
|
||||
#define WM_DOCAPTURE (WM_USER + 100)
|
||||
|
||||
/* Prototypes */
|
||||
void setCaptureType(int capType);
|
||||
BOOL InitApplication(HINSTANCE hInstance);
|
||||
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);
|
||||
int winsnapWinMain(void);
|
||||
|
||||
/* File variables */
|
||||
static int captureType;
|
||||
static char buffer[512];
|
||||
static guchar *capBytes = NULL;
|
||||
static HWND mainHwnd = NULL;
|
||||
static HINSTANCE hInst = NULL;
|
||||
static HCURSOR selectCursor = 0;
|
||||
static ICONINFO iconInfo;
|
||||
|
||||
static gint32 *image_id;
|
||||
|
||||
static void sendBMPToGimp(HBITMAP hBMP, HDC hDC, RECT rect);
|
||||
static void doWindowCapture(void);
|
||||
static int doCapture(HWND selectedHwnd);
|
||||
|
||||
BOOL CALLBACK dialogProc(HWND, UINT, WPARAM, LPARAM);
|
||||
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
||||
|
||||
/* Data structure holding data between runs */
|
||||
typedef struct {
|
||||
gint root;
|
||||
guint delay;
|
||||
gint decor;
|
||||
} WinSnapValues;
|
||||
|
||||
/* Default WinSnap values */
|
||||
static WinSnapValues winsnapvals =
|
||||
{
|
||||
FALSE,
|
||||
0,
|
||||
TRUE,
|
||||
};
|
||||
|
||||
/* The dialog information */
|
||||
typedef struct {
|
||||
#ifdef CAN_SET_DECOR
|
||||
GtkWidget *decor_button;
|
||||
#endif
|
||||
GtkWidget *single_button;
|
||||
GtkWidget *root_button;
|
||||
GtkWidget *delay_spinner;
|
||||
} WinSnapInterface;
|
||||
|
||||
/* The dialog data */
|
||||
static WinSnapInterface winsnapintf =
|
||||
{
|
||||
#ifdef CAN_SET_DECOR
|
||||
NULL,
|
||||
#endif
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* We create a DIB section to hold the grabbed area. The scanlines in
|
||||
* DIB sections are aligned ona LONG (four byte) boundary. Its pixel
|
||||
* data is in RGB (BGR actually) format, three bytes per pixel.
|
||||
*
|
||||
* GIMP uses no alignment for its pixel regions. The GIMP image we
|
||||
* create is of type RGB, i.e. three bytes per pixel, too. Thus in
|
||||
* order to be able to quickly transfer all of the image at a time, we
|
||||
* must use a DIB section and pixel region the scanline width in
|
||||
* bytes of which is evenly divisible with both 3 and 4. I.e. it must
|
||||
* be a multiple of 12 bytes, or in pixels, a multiple of four pixels.
|
||||
*/
|
||||
|
||||
#define ROUND4(width) (((width-1)/4+1)*4)
|
||||
|
||||
|
||||
gboolean
|
||||
screenshot_win32_available (void)
|
||||
{
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ScreenshotCapabilities
|
||||
|
@ -57,7 +145,781 @@ screenshot_win32_shoot (ScreenshotValues *shootvals,
|
|||
gint32 *image_ID,
|
||||
GError **error)
|
||||
{
|
||||
image_id = image_ID;
|
||||
|
||||
winsnapvals.delay = shootvals->select_delay;
|
||||
|
||||
if (shootvals->shoot_type == SHOOT_ROOT)
|
||||
{
|
||||
doCapture(0);
|
||||
return GIMP_PDB_SUCCESS;
|
||||
}
|
||||
else if (shootvals->shoot_type == SHOOT_WINDOW)
|
||||
{
|
||||
doWindowCapture();
|
||||
return GIMP_PDB_SUCCESS;
|
||||
}
|
||||
else if (shootvals->shoot_type == SHOOT_REGION)
|
||||
return GIMP_PDB_EXECUTION_ERROR;
|
||||
|
||||
return GIMP_PDB_EXECUTION_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* GIMP format and transfer functions
|
||||
******************************************************************/
|
||||
|
||||
/*
|
||||
* flipRedAndBlueBytes
|
||||
*
|
||||
* Microsoft has chosen to provide us a very nice (not!)
|
||||
* interface for retrieving bitmap bits. DIBSections have
|
||||
* RGB information as BGR instead. So, we have to swap
|
||||
* the silly red and blue bytes before sending to the
|
||||
* GIMP.
|
||||
*/
|
||||
static void
|
||||
flipRedAndBlueBytes(int width, int height)
|
||||
{
|
||||
int i, j;
|
||||
guchar *bufp;
|
||||
guchar temp;
|
||||
|
||||
j = 0;
|
||||
while (j < height) {
|
||||
i = width;
|
||||
bufp = capBytes + j*ROUND4(width)*3;
|
||||
while (i--) {
|
||||
temp = bufp[2];
|
||||
bufp[2] = bufp[0];
|
||||
bufp[0] = temp;
|
||||
bufp += 3;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sendBMPToGIMP
|
||||
*
|
||||
* Take the captured data and send it across
|
||||
* to GIMP.
|
||||
*/
|
||||
static void
|
||||
sendBMPToGimp(HBITMAP hBMP, HDC hDC, RECT rect)
|
||||
{
|
||||
int width, height;
|
||||
int imageType, layerType;
|
||||
gint32 new_image_id;
|
||||
gint32 layer_id;
|
||||
GimpPixelRgn pixel_rgn;
|
||||
GimpDrawable *drawable;
|
||||
|
||||
/* Our width and height */
|
||||
width = (rect.right - rect.left);
|
||||
height = (rect.bottom - rect.top);
|
||||
|
||||
/* Check that we got the memory */
|
||||
if (!capBytes)
|
||||
{
|
||||
g_message (_("No data captured"));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Flip the red and blue bytes */
|
||||
flipRedAndBlueBytes(width, height);
|
||||
|
||||
/* Set up the image and layer types */
|
||||
imageType = GIMP_RGB;
|
||||
layerType = GIMP_RGB_IMAGE;
|
||||
|
||||
/* Create the GIMP image and layers */
|
||||
new_image_id = gimp_image_new(width, height, imageType);
|
||||
layer_id = gimp_layer_new(new_image_id, _("Background"),
|
||||
ROUND4(width), height,
|
||||
layerType, 100, GIMP_NORMAL_MODE);
|
||||
gimp_image_insert_layer(new_image_id, layer_id, -1, 0);
|
||||
|
||||
/* Get our drawable */
|
||||
drawable = gimp_drawable_get(layer_id);
|
||||
|
||||
gimp_tile_cache_size(ROUND4(width) * gimp_tile_height() * 3);
|
||||
|
||||
/* Initialize a pixel region for writing to the image */
|
||||
gimp_pixel_rgn_init(&pixel_rgn, drawable, 0, 0,
|
||||
ROUND4(width), height, TRUE, FALSE);
|
||||
|
||||
gimp_pixel_rgn_set_rect(&pixel_rgn, (guchar *) capBytes,
|
||||
0, 0, ROUND4(width), height);
|
||||
|
||||
/* HB: update data BEFORE size change */
|
||||
gimp_drawable_flush(drawable);
|
||||
/* Now resize the layer down to the correct size if necessary. */
|
||||
if (width != ROUND4(width)) {
|
||||
gimp_layer_resize (layer_id, width, height, 0, 0);
|
||||
gimp_image_resize (new_image_id, width, height, 0, 0);
|
||||
}
|
||||
/* Finish up */
|
||||
|
||||
*image_id = new_image_id;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* doNonRootWindowCapture
|
||||
*
|
||||
* Capture a selected window.
|
||||
* ENTRY POINT FOR WINSNAP NONROOT
|
||||
*
|
||||
*/
|
||||
static void
|
||||
doWindowCapture(void)
|
||||
{
|
||||
/* Start up a standard Win32
|
||||
* message handling loop for
|
||||
* selection of the window
|
||||
* to be captured
|
||||
*/
|
||||
winsnapWinMain();
|
||||
}
|
||||
|
||||
/*
|
||||
* doRootWindowCapture
|
||||
*
|
||||
* Capture the root window
|
||||
* ENTRY POINT FOR WINSNAP ROOT
|
||||
*/
|
||||
static void
|
||||
doRootWindowCapture(void)
|
||||
{
|
||||
/* Do the window capture */
|
||||
doCapture(0);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* Debug stuff
|
||||
******************************************************************/
|
||||
|
||||
/*
|
||||
* formatWindowsError
|
||||
*
|
||||
* Format the latest Windows error message into
|
||||
* a readable string. Store in the provided
|
||||
* buffer.
|
||||
*/
|
||||
static void
|
||||
formatWindowsError(char *buffer, int buf_size)
|
||||
{
|
||||
LPVOID lpMsgBuf;
|
||||
|
||||
/* Format the message */
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR) &lpMsgBuf, 0, NULL );
|
||||
|
||||
/* Copy to the buffer */
|
||||
strncpy(buffer, lpMsgBuf, buf_size - 1);
|
||||
|
||||
LocalFree(lpMsgBuf);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* Bitmap capture and handling
|
||||
******************************************************************/
|
||||
|
||||
/*
|
||||
* primDoWindowCapture
|
||||
*
|
||||
* The primitive window capture functionality. Accepts
|
||||
* the two device contexts and the rectangle to be
|
||||
* captured.
|
||||
*/
|
||||
static HBITMAP
|
||||
primDoWindowCapture(HDC hdcWindow, HDC hdcCompat, RECT rect)
|
||||
{
|
||||
HBITMAP hbmCopy;
|
||||
HGDIOBJ oldObject;
|
||||
BITMAPINFO bmi;
|
||||
|
||||
int width = (rect.right - rect.left);
|
||||
int height = (rect.bottom - rect.top);
|
||||
|
||||
/* Create the bitmap info header */
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi.bmiHeader.biWidth = ROUND4(width);
|
||||
bmi.bmiHeader.biHeight = -height;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biBitCount = 24;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biSizeImage = 0;
|
||||
bmi.bmiHeader.biXPelsPerMeter =
|
||||
bmi.bmiHeader.biYPelsPerMeter = 0;
|
||||
bmi.bmiHeader.biClrUsed = 0;
|
||||
bmi.bmiHeader.biClrImportant = 0;
|
||||
|
||||
/* Create the bitmap storage space */
|
||||
hbmCopy = CreateDIBSection(hdcCompat,
|
||||
(BITMAPINFO *) &bmi,
|
||||
DIB_RGB_COLORS,
|
||||
(void **)&capBytes, NULL, 0);
|
||||
if (!hbmCopy) {
|
||||
formatWindowsError(buffer, sizeof buffer);
|
||||
g_error("Error creating DIB section: %s", buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Select the bitmap into the compatible DC. */
|
||||
oldObject = SelectObject(hdcCompat, hbmCopy);
|
||||
if (!oldObject) {
|
||||
formatWindowsError(buffer, sizeof buffer);
|
||||
g_error("Error selecting object: %s", buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Copy the data from the application to the bitmap. Even if we did
|
||||
* round up the width, BitBlt only the actual data.
|
||||
*/
|
||||
if (!BitBlt(hdcCompat, 0,0,
|
||||
width, height,
|
||||
hdcWindow, 0,0,
|
||||
SRCCOPY)) {
|
||||
formatWindowsError(buffer, sizeof buffer);
|
||||
g_error("Error copying bitmap: %s", buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Restore the original object */
|
||||
SelectObject(hdcCompat, oldObject);
|
||||
|
||||
return hbmCopy;
|
||||
}
|
||||
|
||||
/*
|
||||
* doCapture
|
||||
*
|
||||
* Do the capture. Accepts the window
|
||||
* handle to be captured or the NULL value
|
||||
* to specify the root window.
|
||||
*/
|
||||
static int
|
||||
doCapture(HWND selectedHwnd)
|
||||
{
|
||||
HDC hdcSrc;
|
||||
HDC hdcCompat;
|
||||
HRGN capRegion;
|
||||
HWND oldForeground;
|
||||
RECT rect;
|
||||
HBITMAP hbm;
|
||||
|
||||
/* Try and get everything out of the way before the
|
||||
* capture.
|
||||
*/
|
||||
Sleep(500 + winsnapvals.delay * 1000);
|
||||
|
||||
/* Are we capturing a window or the whole screen */
|
||||
if (selectedHwnd) {
|
||||
|
||||
/* Set to foreground window */
|
||||
oldForeground = GetForegroundWindow();
|
||||
SetForegroundWindow(selectedHwnd);
|
||||
BringWindowToTop(selectedHwnd);
|
||||
|
||||
Sleep(500);
|
||||
|
||||
/* Build a region for the capture */
|
||||
GetWindowRect(selectedHwnd, &rect);
|
||||
capRegion = CreateRectRgn(rect.left, rect.top,
|
||||
rect.right, rect.bottom);
|
||||
if (!capRegion) {
|
||||
formatWindowsError(buffer, sizeof buffer);
|
||||
g_error("Error creating region: %s", buffer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Get the device context for the selected
|
||||
* window. Create a memory DC to use for the
|
||||
* Bit copy.
|
||||
*/
|
||||
hdcSrc = GetDCEx(selectedHwnd, capRegion,
|
||||
DCX_WINDOW | DCX_PARENTCLIP | DCX_INTERSECTRGN);
|
||||
} else {
|
||||
/* Get the device context for the whole screen */
|
||||
hdcSrc = CreateDC("DISPLAY", NULL, NULL, NULL);
|
||||
|
||||
/* Get the screen's rectangle */
|
||||
rect.top = 0;
|
||||
rect.bottom = GetDeviceCaps(hdcSrc, VERTRES);
|
||||
rect.left = 0;
|
||||
rect.right = GetDeviceCaps(hdcSrc, HORZRES);
|
||||
}
|
||||
|
||||
if (!hdcSrc) {
|
||||
formatWindowsError(buffer, sizeof buffer);
|
||||
g_error("Error getting device context: %s", buffer);
|
||||
return FALSE;
|
||||
}
|
||||
hdcCompat = CreateCompatibleDC(hdcSrc);
|
||||
if (!hdcCompat) {
|
||||
formatWindowsError(buffer, sizeof buffer);
|
||||
g_error("Error getting compat device context: %s", buffer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Do the window capture */
|
||||
hbm = primDoWindowCapture(hdcSrc, hdcCompat, rect);
|
||||
if (!hbm)
|
||||
return FALSE;
|
||||
|
||||
/* Release the device context */
|
||||
ReleaseDC(selectedHwnd, hdcSrc);
|
||||
|
||||
/* Replace the previous foreground window */
|
||||
if (selectedHwnd && oldForeground)
|
||||
SetForegroundWindow(oldForeground);
|
||||
|
||||
/* Send the bitmap
|
||||
* TODO: Change this
|
||||
*/
|
||||
if (hbm != NULL) {
|
||||
sendBMPToGimp(hbm, hdcCompat, rect);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* Win32 entry point and setup...
|
||||
******************************************************************/
|
||||
|
||||
#define DINV 3
|
||||
|
||||
/*
|
||||
* highlightWindowFrame
|
||||
*
|
||||
* Highlight (or unhighlight) the specified
|
||||
* window handle's frame.
|
||||
*/
|
||||
static void
|
||||
highlightWindowFrame(HWND hWnd)
|
||||
{
|
||||
HDC hdc;
|
||||
RECT rc;
|
||||
|
||||
if (!IsWindow(hWnd))
|
||||
return;
|
||||
|
||||
hdc = GetWindowDC(hWnd);
|
||||
GetWindowRect(hWnd, &rc);
|
||||
OffsetRect(&rc, -rc.left, -rc.top);
|
||||
|
||||
if (!IsRectEmpty(&rc)) {
|
||||
PatBlt(hdc, rc.left, rc.top, rc.right-rc.left, DINV, DSTINVERT);
|
||||
PatBlt(hdc, rc.left, rc.bottom-DINV, DINV, -(rc.bottom-rc.top-2*DINV),
|
||||
DSTINVERT);
|
||||
PatBlt(hdc, rc.right-DINV, rc.top+DINV, DINV, rc.bottom-rc.top-2*DINV,
|
||||
DSTINVERT);
|
||||
PatBlt(hdc, rc.right, rc.bottom-DINV, -(rc.right-rc.left), DINV,
|
||||
DSTINVERT);
|
||||
}
|
||||
|
||||
ReleaseDC(hWnd, hdc);
|
||||
UpdateWindow(hWnd);
|
||||
}
|
||||
|
||||
/*
|
||||
* setCaptureType
|
||||
*
|
||||
* Set the capture type. Should be one of:
|
||||
* SELECT_FRAME
|
||||
* SELECT_CLIENT
|
||||
* SELECT_WINDOW
|
||||
*/
|
||||
void
|
||||
setCaptureType(int capType)
|
||||
{
|
||||
captureType = capType;
|
||||
}
|
||||
|
||||
/*
|
||||
* myWindowFromPoint
|
||||
*
|
||||
* Map to the appropriate window from the
|
||||
* specified point. The chosen window is
|
||||
* based on the current capture type.
|
||||
*/
|
||||
static HWND
|
||||
myWindowFromPoint(POINT pt)
|
||||
{
|
||||
HWND myHwnd;
|
||||
HWND nextHwnd;
|
||||
|
||||
switch (captureType) {
|
||||
case SELECT_FRAME:
|
||||
case SELECT_CLIENT:
|
||||
nextHwnd = WindowFromPoint(pt);
|
||||
|
||||
do {
|
||||
myHwnd = nextHwnd;
|
||||
nextHwnd = GetParent(myHwnd);
|
||||
} while (nextHwnd);
|
||||
|
||||
return myHwnd;
|
||||
break;
|
||||
|
||||
case SELECT_WINDOW:
|
||||
return WindowFromPoint(pt);
|
||||
break;
|
||||
}
|
||||
|
||||
return WindowFromPoint(pt);
|
||||
}
|
||||
|
||||
/*
|
||||
* dialogProc
|
||||
*
|
||||
* The window procedure for the window
|
||||
* selection dialog box.
|
||||
*/
|
||||
BOOL CALLBACK
|
||||
dialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static int mouseCaptured;
|
||||
static int buttonDown;
|
||||
static HCURSOR oldCursor;
|
||||
static RECT bitmapRect;
|
||||
static HWND highlightedHwnd = NULL;
|
||||
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
int nonclientHeight;
|
||||
HWND hwndGroup;
|
||||
RECT dlgRect;
|
||||
RECT clientRect;
|
||||
RECT groupRect;
|
||||
BITMAP bm;
|
||||
|
||||
/* Set the mouse capture flag */
|
||||
buttonDown = 0;
|
||||
mouseCaptured = 0;
|
||||
|
||||
/* Calculate the bitmap dimensions */
|
||||
GetObject(iconInfo.hbmMask, sizeof(BITMAP), (VOID *)&bm);
|
||||
|
||||
/* Calculate the dialog window dimensions */
|
||||
GetWindowRect(hwndDlg, &dlgRect);
|
||||
|
||||
/* Calculate the group box dimensions */
|
||||
hwndGroup = GetDlgItem(hwndDlg, IDC_GROUP);
|
||||
GetWindowRect(hwndGroup, &groupRect);
|
||||
OffsetRect(&groupRect, -dlgRect.left, -dlgRect.top);
|
||||
|
||||
/* The client's rectangle */
|
||||
GetClientRect(hwndDlg, &clientRect);
|
||||
|
||||
/* The non-client height */
|
||||
nonclientHeight = (dlgRect.bottom - dlgRect.top) -
|
||||
(clientRect.bottom - clientRect.top);
|
||||
|
||||
/* Calculate the bitmap rectangle */
|
||||
bitmapRect.top = ((groupRect.top + groupRect.bottom) / 2) -
|
||||
(bm.bmHeight / 2);
|
||||
bitmapRect.top -= nonclientHeight;
|
||||
bitmapRect.bottom = bitmapRect.top + bm.bmHeight;
|
||||
bitmapRect.left = ((groupRect.left + groupRect.right) / 2) - (bm.bmWidth / 2);
|
||||
bitmapRect.right = bitmapRect.left + bm.bmWidth;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
/* Track the button down state */
|
||||
buttonDown = 1;
|
||||
break;
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
buttonDown = 0;
|
||||
|
||||
/* If we have mouse captured
|
||||
* we do this stuff.
|
||||
*/
|
||||
if (mouseCaptured) {
|
||||
HWND selectedHwnd;
|
||||
POINT cursorPos;
|
||||
|
||||
/* Release the capture */
|
||||
mouseCaptured = 0;
|
||||
SetCursor(oldCursor);
|
||||
ReleaseCapture();
|
||||
|
||||
/* Remove the highlight */
|
||||
if (highlightedHwnd)
|
||||
highlightWindowFrame(highlightedHwnd);
|
||||
RedrawWindow(hwndDlg, NULL, NULL, RDW_INVALIDATE);
|
||||
|
||||
/* Return the selected window */
|
||||
GetCursorPos(&cursorPos);
|
||||
selectedHwnd = myWindowFromPoint(cursorPos);
|
||||
EndDialog(hwndDlg, (INT_PTR) selectedHwnd);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
/* If the mouse is captured, show
|
||||
* the window which is tracking
|
||||
* under the mouse position.
|
||||
*/
|
||||
if (mouseCaptured) {
|
||||
HWND currentHwnd;
|
||||
POINT cursorPos;
|
||||
|
||||
/* Get the window */
|
||||
GetCursorPos(&cursorPos);
|
||||
currentHwnd = myWindowFromPoint(cursorPos);
|
||||
|
||||
/* Do the highlighting */
|
||||
if (highlightedHwnd != currentHwnd) {
|
||||
if (highlightedHwnd)
|
||||
highlightWindowFrame(highlightedHwnd);
|
||||
if (currentHwnd)
|
||||
highlightWindowFrame(currentHwnd);
|
||||
highlightedHwnd = currentHwnd;
|
||||
}
|
||||
/* If the mouse has not been captured,
|
||||
* try to figure out if we should capture
|
||||
* the mouse.
|
||||
*/
|
||||
} else if (buttonDown) {
|
||||
POINT cursorPos;
|
||||
|
||||
/* Get the current client position */
|
||||
GetCursorPos(&cursorPos);
|
||||
ScreenToClient(hwndDlg, &cursorPos);
|
||||
|
||||
/* Check if within the rectangle formed
|
||||
* by the bitmap
|
||||
*/
|
||||
if (PtInRect(&bitmapRect, cursorPos)) {
|
||||
mouseCaptured = 1;
|
||||
oldCursor = SetCursor(selectCursor);
|
||||
SetCapture(hwndDlg);
|
||||
RedrawWindow(hwndDlg, NULL, NULL, RDW_INVALIDATE | RDW_ERASE);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WM_PAINT:
|
||||
{
|
||||
HDC hDC;
|
||||
PAINTSTRUCT ps;
|
||||
|
||||
/* If the mouse is not captured draw
|
||||
* the cursor image
|
||||
*/
|
||||
if (!mouseCaptured) {
|
||||
hDC = BeginPaint(hwndDlg, &ps);
|
||||
DrawIconEx(hDC, bitmapRect.left, bitmapRect.top, selectCursor,
|
||||
0, 0, 0, NULL, DI_NORMAL);
|
||||
EndPaint(hwndDlg, &ps);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
/* Handle the cancel button */
|
||||
switch (LOWORD(wParam)) {
|
||||
case IDCANCEL:
|
||||
EndDialog(hwndDlg, 0);
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
///* Don't use the normal WinMain from gimp.h */
|
||||
//#define WinMain WinMain_no_thanks
|
||||
//MAIN()
|
||||
//#undef WinMain
|
||||
|
||||
/*
|
||||
* WinMain
|
||||
*
|
||||
* The standard gimp plug-in WinMain won't quite cut it for
|
||||
* this plug-in.
|
||||
*/
|
||||
//int APIENTRY
|
||||
//WinMain(HINSTANCE hInstance,
|
||||
// HINSTANCE hPrevInstance,
|
||||
// LPSTR lpCmdLine,
|
||||
// int nCmdShow)
|
||||
//{
|
||||
// /*
|
||||
// * Normally, we would do all of the Windows-ish set up of
|
||||
// * the window classes and stuff here in WinMain. But,
|
||||
// * the only time we really need the window and message
|
||||
// * queues is during the plug-in run. So, all of that will
|
||||
// * be done during run(). This avoids all of the Windows
|
||||
// * setup stuff for the query(). Stash the instance handle now
|
||||
// * so it is available from the run() procedure.
|
||||
// */
|
||||
// hInst = hInstance;
|
||||
//
|
||||
// /*
|
||||
// * Now, call gimp_main... This is what the normal WinMain()
|
||||
// * would do.
|
||||
// */
|
||||
//// return gimp_main(&PLUG_IN_INFO, __argc, __argv);
|
||||
//}
|
||||
|
||||
/*
|
||||
* InitApplication
|
||||
*
|
||||
* Initialize window data and register the window class
|
||||
*/
|
||||
BOOL
|
||||
InitApplication(HINSTANCE hInstance)
|
||||
{
|
||||
WNDCLASS wc;
|
||||
BOOL retValue;
|
||||
|
||||
/* Get some resources */
|
||||
#ifdef _MSC_VER
|
||||
/* For some reason this works only with MSVC */
|
||||
selectCursor = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_SELECT));
|
||||
#else
|
||||
selectCursor = LoadCursor(NULL, IDC_CROSS);
|
||||
#endif
|
||||
GetIconInfo(selectCursor, &iconInfo);
|
||||
|
||||
/*
|
||||
* Fill in window class structure with parameters to describe
|
||||
* the main window.
|
||||
*/
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = (WNDPROC) WndProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = hInstance;
|
||||
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
|
||||
wc.lpszClassName = APP_NAME;
|
||||
wc.lpszMenuName = NULL;
|
||||
|
||||
/* Register the window class and stash success/failure code. */
|
||||
retValue = RegisterClass(&wc);
|
||||
|
||||
/* Log error */
|
||||
if (!retValue) {
|
||||
formatWindowsError(buffer, sizeof buffer);
|
||||
g_error("Error registering class: %s", buffer);
|
||||
return retValue;
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* InitInstance
|
||||
*
|
||||
* Create the main window for the application.
|
||||
*/
|
||||
BOOL
|
||||
InitInstance(HINSTANCE hInstance, int nCmdShow)
|
||||
{
|
||||
/* Create our window */
|
||||
mainHwnd = CreateWindow(APP_NAME, APP_NAME, WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
|
||||
NULL, NULL, hInstance, NULL);
|
||||
|
||||
if (!mainHwnd) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
ShowWindow(mainHwnd, nCmdShow);
|
||||
UpdateWindow(mainHwnd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* winsnapWinMain
|
||||
*
|
||||
* This is the function that represents the code that
|
||||
* would normally reside in WinMain (see above). This
|
||||
* function will get called during run() in order to set
|
||||
* up the windowing environment necessary for WinSnap to
|
||||
* operate.
|
||||
*/
|
||||
int
|
||||
winsnapWinMain(void)
|
||||
{
|
||||
MSG msg;
|
||||
|
||||
/* Perform instance initialization */
|
||||
if (!InitApplication(hInst))
|
||||
return (FALSE);
|
||||
|
||||
/* Perform application initialization */
|
||||
if (!InitInstance(hInst, SHOW_WINDOW))
|
||||
return (FALSE);
|
||||
|
||||
/* Main message loop */
|
||||
while (GetMessage(&msg, NULL, 0, 0)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
return (msg.wParam);
|
||||
}
|
||||
|
||||
/*
|
||||
* WndProc
|
||||
*
|
||||
* Process window message for the main window.
|
||||
*/
|
||||
LRESULT CALLBACK
|
||||
WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
HWND selectedHwnd;
|
||||
|
||||
switch (message) {
|
||||
|
||||
case WM_CREATE:
|
||||
/* The window is created... Send the capture message */
|
||||
PostMessage(hwnd, WM_DOCAPTURE, 0, 0);
|
||||
break;
|
||||
|
||||
case WM_DOCAPTURE:
|
||||
/* Get the selected window handle */
|
||||
selectedHwnd = (HWND) DialogBox(hInst, MAKEINTRESOURCE(IDD_SELECT),
|
||||
hwnd, (DLGPROC) dialogProc);
|
||||
if (selectedHwnd)
|
||||
doCapture(selectedHwnd);
|
||||
|
||||
PostQuitMessage(0);
|
||||
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (DefWindowProc(hwnd, message, wParam, lParam));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* G_OS_WIN32 */
|
||||
|
|
|
@ -21,6 +21,14 @@
|
|||
|
||||
#ifdef G_OS_WIN32
|
||||
|
||||
#define IDC_STATIC -1
|
||||
|
||||
#define IDS_APP_TITLE 500
|
||||
#define IDS_DISPLAYCHANGED 501
|
||||
#define IDS_VER_INFO_LANG 502
|
||||
#define IDS_VERSION_ERROR 503
|
||||
#define IDS_NO_HELP 504
|
||||
|
||||
gboolean screenshot_win32_available (void);
|
||||
|
||||
ScreenshotCapabilities screenshot_win32_get_capabilities (void);
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1,189 @@
|
|||
//Microsoft Developer Studio 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
|
||||
#include "screenshot-win32.h"
|
||||
#include "winver.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
SNAPPY ICON DISCARDABLE "screenshot-win32.ico"
|
||||
SMALL ICON DISCARDABLE "small.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Menu
|
||||
//
|
||||
|
||||
SNAPPY MENU DISCARDABLE
|
||||
BEGIN
|
||||
POPUP "&File"
|
||||
BEGIN
|
||||
MENUITEM "&Capture", IDM_CAPTURE
|
||||
MENUITEM "Capture Fullscreen", IDM_CAPTUREFULL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Begin Hook", IDM_HOOK
|
||||
MENUITEM "End Hook", IDM_UNHOOK
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "E&xit", IDM_EXIT
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"#include ""windows.h""\r\n"
|
||||
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"#include ""screenshot-win32.h""\r\n"
|
||||
"#include ""winver.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Cursor
|
||||
//
|
||||
|
||||
IDC_SELECT CURSOR DISCARDABLE "select.cur"
|
||||
|
||||
#ifndef _MAC
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,1
|
||||
PRODUCTVERSION 1,0,0,1
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "000004b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "\0"
|
||||
VALUE "CompanyName", "SeteraSoft\0"
|
||||
VALUE "FileDescription", "snappy\0"
|
||||
VALUE "FileVersion", "1, 0, 0, 1\0"
|
||||
VALUE "InternalName", "snappy\0"
|
||||
VALUE "LegalCopyright", "Copyright © 1999\0"
|
||||
VALUE "LegalTrademarks", "\0"
|
||||
VALUE "OriginalFilename", "snappy.exe\0"
|
||||
VALUE "PrivateBuild", "\0"
|
||||
VALUE "ProductName", "SeteraSoft snappy\0"
|
||||
VALUE "ProductVersion", "1, 0, 0, 1\0"
|
||||
VALUE "SpecialBuild", "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // !_MAC
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_SELECT DIALOG DISCARDABLE 0, 0, 141, 95
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Select Window"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
PUSHBUTTON "Cancel",IDCANCEL,44,74,50,14
|
||||
CTEXT "Drag crosshair to select window",IDC_TEXT,7,7,127,8
|
||||
GROUPBOX "",IDC_GROUP,51,25,37,37,NOT WS_VISIBLE
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO DISCARDABLE
|
||||
BEGIN
|
||||
IDD_SELECT, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 134
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 88
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 326 B |
Binary file not shown.
After Width: | Height: | Size: 318 B |
Loading…
Reference in New Issue