[gimp/gimp-attributes-wip: 16/16] plug-ins: convert win-snap to screenshot works as win-snap, lots of optimizing work to be done.



commit 64ee853bf594a7baaa37ae326820e30d80a686a4
Author: Hartmut Kuhse <hk_priv gmx de>
Date:   Sun May 1 19:02:05 2016 +0200

    plug-ins: convert win-snap to screenshot
    works as win-snap, lots of optimizing work to be done.

 plug-ins/screenshot/Makefile.am          |   19 +-
 plug-ins/screenshot/resource.h           |   26 +
 plug-ins/screenshot/screenshot-win32.c   |  864 +++++++++++++++++++++++++++++-
 plug-ins/screenshot/screenshot-win32.h   |    8 +
 plug-ins/screenshot/screenshot-win32.ico |  Bin 0 -> 1590 bytes
 plug-ins/screenshot/screenshot-win32.rc  |  189 +++++++
 plug-ins/screenshot/select.cur           |  Bin 0 -> 326 bytes
 plug-ins/screenshot/small.ico            |  Bin 0 -> 318 bytes
 8 files changed, 1100 insertions(+), 6 deletions(-)
---
diff --git a/plug-ins/screenshot/Makefile.am b/plug-ins/screenshot/Makefile.am
index 75015ae..91b8ea8 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 0000000..57b6ec2
--- /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 dd832ed..e15f7a1 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 66adf27..2e80c0d 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 0000000..35ea973
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 0000000..5146652
--- /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 0000000..2357f84
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 0000000..33f9a51
Binary files /dev/null and b/plug-ins/screenshot/small.ico differ


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]