diff --git a/plug-ins/screenshot/Makefile.am b/plug-ins/screenshot/Makefile.am index 75015ae59f..91b8ea8b63 100644 --- a/plug-ins/screenshot/Makefile.am +++ b/plug-ins/screenshot/Makefile.am @@ -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 diff --git a/plug-ins/screenshot/resource.h b/plug-ins/screenshot/resource.h new file mode 100644 index 0000000000..57b6ec2601 --- /dev/null +++ b/plug-ins/screenshot/resource.h @@ -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 diff --git a/plug-ins/screenshot/screenshot-win32.c b/plug-ins/screenshot/screenshot-win32.c index dd832edde7..e15f7a1b9d 100644 --- a/plug-ins/screenshot/screenshot-win32.c +++ b/plug-ins/screenshot/screenshot-win32.c @@ -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 */ diff --git a/plug-ins/screenshot/screenshot-win32.h b/plug-ins/screenshot/screenshot-win32.h index 66adf27567..2e80c0dafd 100644 --- a/plug-ins/screenshot/screenshot-win32.h +++ b/plug-ins/screenshot/screenshot-win32.h @@ -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); diff --git a/plug-ins/screenshot/screenshot-win32.ico b/plug-ins/screenshot/screenshot-win32.ico new file mode 100644 index 0000000000..35ea9738b4 Binary files /dev/null and b/plug-ins/screenshot/screenshot-win32.ico differ diff --git a/plug-ins/screenshot/screenshot-win32.rc b/plug-ins/screenshot/screenshot-win32.rc new file mode 100644 index 0000000000..51466522d4 --- /dev/null +++ b/plug-ins/screenshot/screenshot-win32.rc @@ -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 + diff --git a/plug-ins/screenshot/select.cur b/plug-ins/screenshot/select.cur new file mode 100644 index 0000000000..2357f84228 Binary files /dev/null and b/plug-ins/screenshot/select.cur differ diff --git a/plug-ins/screenshot/small.ico b/plug-ins/screenshot/small.ico new file mode 100644 index 0000000000..33f9a51f8d Binary files /dev/null and b/plug-ins/screenshot/small.ico differ