Click here to Skip to main content
15,886,689 members
Articles / Desktop Programming / MFC

Screen capture, window resizing utility with source code

Rate me:
Please Sign up or sign in to vote.
4.77/5 (50 votes)
1 Jul 20055 min read 266.2K   8.1K   124  
This utility uses Lim Bio Liong's excellent Spy++ style Window Finder code to build a screen capture utility (featuring text capture as well as bitmaps) and window resizer/mover. It also demonstrates stay on top and expanding/contracting (i.e. more detail / less detail) dialog boxes.

#include "stdafx.h"
#include "WindowFinder.h"
#include "WinScraper.h"
#include "resource.h"



#define BULLSEYE_CENTER_X_OFFSET		15
#define BULLSEYE_CENTER_Y_OFFSET		18


HWND		g_hwndFoundWindow = NULL;
HCURSOR		g_hCursorPrevious = NULL;
BOOL		g_bStartSearchWindow = FALSE;
HBITMAP		g_hBitmapFinderToolFilled;
HBITMAP		g_hBitmapFinderToolEmpty;
HCURSOR		g_hCursorSearchWindow = NULL;
HINSTANCE	g_hInst = NULL;
HPEN		g_hRectanglePen = NULL;

BOOL InitialiseResources()
{
  BOOL bRet = FALSE;

  g_hInst=AfxGetApp()->m_hInstance;

  g_hCursorSearchWindow = LoadCursor (g_hInst, MAKEINTRESOURCE(IDC_CURSOR_SEARCH_WINDOW));
  if (g_hCursorSearchWindow == NULL)
  {
    bRet = FALSE;
  }

  g_hRectanglePen = CreatePen (PS_SOLID, 5, RGB(255, 0, 0));
  if (g_hRectanglePen == NULL)
  {
    bRet = FALSE;
  }

  g_hBitmapFinderToolFilled = LoadBitmap (g_hInst, MAKEINTRESOURCE(IDB_BITMAP_FINDER_FILLED));
  if (g_hBitmapFinderToolFilled == NULL)
  {
    bRet = FALSE;
  }

  g_hBitmapFinderToolEmpty = LoadBitmap (g_hInst, MAKEINTRESOURCE(IDB_BITMAP_FINDER_EMPTY));
  if (g_hBitmapFinderToolEmpty == NULL)
  {
    bRet = FALSE;
  }

  // All went well. Return TRUE.
  bRet = TRUE;

  return bRet;
}


// Synopsis :
// 1. This function checks a hwnd to see if it is actually the "Search Window" Dialog's or Main Window's
// own window or one of their children. If so a FALSE will be returned so that these windows will not
// be selected. 
//
// 2. Also, this routine checks to see if the hwnd to be checked is already a currently found window.
// If so, a FALSE will also be returned to avoid repetitions.
BOOL CheckWindowValidity (HWND hwndDialog, HWND hwndToCheck)
{
  HWND hwndTemp = NULL;
  BOOL bRet = TRUE;

  // The window must not be NULL.
  if (hwndToCheck == NULL)
  {
    bRet = FALSE;
	goto CheckWindowValidity_0;
  }

  // It must also be a valid window as far as the OS is concerned.
  if (IsWindow(hwndToCheck) == FALSE)
  {
    bRet = FALSE;
	goto CheckWindowValidity_0;
  }

  // Ensure that the window is not the current one which has already been found.
  if (hwndToCheck == g_hwndFoundWindow)
  {
    bRet = FALSE;
	goto CheckWindowValidity_0;
  }

  
  // It also must not be the "Search Window" dialog box itself.
  if (hwndToCheck == hwndDialog)
  {
    bRet = FALSE;
	goto CheckWindowValidity_0;
  }

  // It also must not be one of the dialog box's children...
  hwndTemp = GetParent (hwndToCheck);
  if ((hwndTemp == hwndDialog))
  {
    bRet = FALSE;
	goto CheckWindowValidity_0;
  }

CheckWindowValidity_0:

  return bRet;
}



// Synopsis :
// 1. This is the handler for WM_MOUSEMOVE messages sent to the "Search Window" dialog proc.
//
// 2. Note that we do not handle every WM_MOUSEMOVE message sent. Instead, we check to see 
// if "g_bStartSearchWindow" is TRUE. This BOOL will be set to TRUE when the Window
// Searching Operation is actually started. See the WM_COMMAND message handler in 
// SearchWindowDialogProc() for more details.
//
// 3. Because the "Search Window" dialog immediately captures the mouse when the Search Operation 
// is started, all mouse movement is monitored by the "Search Window" dialog box. This is 
// regardless of whether the mouse is within or without the "Search Window" dialog. 
//
// 4. One important note is that the horizontal and vertical positions of the mouse cannot be 
// calculated from "lParam". These values can be inaccurate when the mouse is outside the
// dialog box. Instead, use the GetCursorPos() API to capture the position of the mouse.
long DoMouseMove 
(
  HWND hwndDialog, 
  UINT message, 
  WPARAM wParam, 
  LPARAM lParam
)
{
  POINT		screenpoint;
  HWND		hwndFoundWindow = NULL;
  char		szText[256];
  long		lRet = 0;

  // Must use GetCursorPos() instead of calculating from "lParam".
  GetCursorPos (&screenpoint);  

  // Display global positioning in the dialog box.
  wsprintf (szText, "%d", screenpoint.x);
  SetDlgItemText (hwndDialog, IDC_XPOS_EDIT, szText);
  
  wsprintf (szText, "%d", screenpoint.y);
  SetDlgItemText (hwndDialog, IDC_YPOS_EDIT, szText);

  // Determine the window that lies underneath the mouse cursor.
  hwndFoundWindow = WindowFromPoint (screenpoint);

  // Check first for validity.
  if (CheckWindowValidity (hwndDialog, hwndFoundWindow))
  {
    // We have just found a new window.

    // Display some information on this found window.
	DisplayInfoOnFoundWindow (hwndDialog, hwndFoundWindow);

    // If there was a previously found window, we must instruct it to refresh itself. 
	// This is done to remove any highlighting effects drawn by us.
    if (g_hwndFoundWindow)
    {
      RefreshWindow (g_hwndFoundWindow);
    }

    // Indicate that this found window is now the current global found window.
    g_hwndFoundWindow = hwndFoundWindow;

    // We now highlight the found window.
    HighlightFoundWindow (hwndDialog, g_hwndFoundWindow);
  }

  return lRet;
}





// Synopsis :
// 1. Handler for WM_LBUTTONUP message sent to the "Search Window" dialog box.
// 
// 2. We restore the screen cursor to the previous one.
//
// 3. We stop the window search operation and release the mouse capture.
long DoMouseUp
(
  HWND hwndDialog, 
  UINT message, 
  WPARAM wParam, 
  LPARAM lParam
)
{
  long lRet = 0;

  // If we had a previous cursor, set the screen cursor to the previous one.
  // The cursor is to stay exactly where it is currently located when the 
  // left mouse button is lifted.
  if (g_hCursorPrevious)
  {
    SetCursor (g_hCursorPrevious);
  }

  // If there was a found window, refresh it so that its highlighting is erased. 
  if (g_hwndFoundWindow)
  {
    RefreshWindow (g_hwndFoundWindow);
  }

  // Set the bitmap on the Finder Tool icon to be the bitmap with the bullseye bitmap.
  SetFinderToolImage (hwndDialog, TRUE);

  // Get the screen coordinates of the rectangle of the found window.
  RECT		rect;              // Rectangle area of the found window.
  GetWindowRect (g_hwndFoundWindow, &rect);

  SetDlgItemInt(hwndDialog, IDC_XPOS_EDIT, rect.left, TRUE);
  SetDlgItemInt(hwndDialog, IDC_YPOS_EDIT, rect.top, TRUE);


  // Very important : must release the mouse capture.
  ReleaseCapture ();


  // Set the global search window flag to FALSE.
  g_bStartSearchWindow = FALSE;

  return lRet;
}





// Synopsis :
// 1. This routine sets the Finder Tool icon to contain an appropriate bitmap.
//
// 2. If bSet is TRUE, we display the BullsEye bitmap. Otherwise the empty window
// bitmap is displayed.
BOOL SetFinderToolImage (HWND hwndDialog, BOOL bSet)
{
  HBITMAP hBmpToSet = NULL;
  BOOL bRet = TRUE;

  if (bSet)
  {
    // Set a FILLED image.
	hBmpToSet = g_hBitmapFinderToolFilled;
  }
  else
  {
    // Set an EMPTY image.
	hBmpToSet = g_hBitmapFinderToolEmpty;
  }

  SendDlgItemMessage
  (
    (HWND)hwndDialog, // handle of dialog box 
    (int)IDC_STATIC_ICON_FINDER_TOOL, // identifier of control 
    (UINT)STM_SETIMAGE, // message to send 
    (WPARAM)IMAGE_BITMAP, // first message parameter 
    (LPARAM)hBmpToSet // second message parameter 
  );

  return bRet;
}





// Synopsis :
// 1. This routine moves the mouse cursor hotspot to the exact 
// centre position of the bullseye in the finder tool static control.
//
// 2. This function, when used together with DoSetFinderToolImage(),
// gives the illusion that the bullseye image has indeed been transformed
// into a cursor and can be moved away from the Finder Tool Static
// control.
BOOL MoveCursorPositionToBullsEye (HWND hwndDialog)
{
  BOOL bRet = FALSE;
  HWND hwndToolFinder = NULL;
  RECT rect;
  POINT screenpoint;

  // Get the window handle of the Finder Tool static control.
  hwndToolFinder = GetDlgItem (hwndDialog, IDC_STATIC_ICON_FINDER_TOOL);

  if (hwndToolFinder)
  {
    // Get the screen coordinates of the static control,
	// add the appropriate pixel offsets to the center of 
	// the bullseye and move the mouse cursor to this exact
	// position.
    GetWindowRect (hwndToolFinder, &rect);
	screenpoint.x = rect.left + BULLSEYE_CENTER_X_OFFSET;
    screenpoint.y = rect.top + BULLSEYE_CENTER_Y_OFFSET;
	SetCursorPos (screenpoint.x, screenpoint.y);
  }

  return bRet;
}





// Synopsis :
// 1. This function starts the window searching operation.
//
// 2. A very important part of this function is to capture 
// all mouse activities from now onwards and direct all mouse 
// messages to the "Search Window" dialog box procedure.
long SearchWindow (HWND hwndDialog)
{
  long lRet = 0;

  // Set the global "g_bStartSearchWindow" flag to TRUE.
  g_bStartSearchWindow = TRUE;

  // Display the empty window bitmap image in the Finder Tool static control.
  SetFinderToolImage (hwndDialog, FALSE);

  MoveCursorPositionToBullsEye (hwndDialog);

  // Set the screen cursor to the BullsEye cursor.
  if (g_hCursorSearchWindow)
  {
    g_hCursorPrevious = SetCursor (g_hCursorSearchWindow);
  }
  else
  {
    g_hCursorPrevious = NULL;
  }

  // Very important : capture all mouse activities from now onwards and
  // direct all mouse messages to the "Search Window" dialog box procedure.
  SetCapture (hwndDialog);

  
  return lRet;
}





long DisplayInfoOnFoundWindow (HWND hwndDialog, HWND hwndFoundWindow)
{
  RECT		rect;              // Rectangle area of the found window.
  char		szText[5500];
  char		szClassName[100];
  long		lRet = 0;

  // Get the screen coordinates of the rectangle of the found window.
  GetWindowRect (hwndFoundWindow, &rect);

  // Get the class name of the found window.
  GetClassName (hwndFoundWindow, szClassName, sizeof (szClassName) - 1);

  DWORD nCtrlID=GetDlgCtrlID(hwndFoundWindow);


  // Display some information on the found window.
  wsprintf
  (
  szText, "Window Handle == 0x%08X.\r\nClass Name : %s.\r\nControl ID : 0x%X\r\nRECT.left \t=%d\tRECT.top  \t=%d\r\nRECT.right  \t=%d\tRECT.bottom \t=%d",
    hwndFoundWindow,
	szClassName,
	nCtrlID,
    rect.left,
    rect.top,
    rect.right,
    rect.bottom
  );

  SetDlgItemText (hwndDialog, IDC_EDIT_STATUS, szText);

  SetDlgItemInt(hwndDialog, IDC_WIDTH_EDIT, rect.right-rect.left, TRUE);
  SetDlgItemInt(hwndDialog, IDC_HEIGHT_EDIT, rect.bottom-rect.top, TRUE);

  
  // Get window text
  int count, nItems;
  BOOL bGot=FALSE;
  CString strItem;
  char winTxt[5000];
  memset(winTxt, 0, 5000);

  // Is it a ListBox?
  if(strcmp(szClassName, "ListBox") == 0)
  {
	  CListBox lb;
	  lb.Attach(hwndFoundWindow);
	  nItems=lb.GetCount();
	  for(count=0; count < nItems; count++)
	  {
		  lb.GetText(count, strItem);
		  strItem+="\r\n";
		  strcat(winTxt, strItem);
	  }
	  lb.Detach();
	  bGot=TRUE;
  }

  // Is it a ComboBox?
  if(strcmp(szClassName, "ComboBox") == 0)
  {
	  CComboBox cb;
	  cb.Attach(hwndFoundWindow);
	  int nItems=cb.GetCount();
	  for(count=0; count < nItems; count++)
	  {
		  cb.GetLBText(count, strItem);
		  if(cb.GetCurSel() == count)
			  strItem+=(" <- Selected");
		  strItem+="\r\n";
		  strcat(winTxt, strItem);
	  }
	  cb.Detach();
	  bGot=TRUE;
  }


  
  // Catch all, if we haven't got the window's text yet
  if(!bGot)
	SendMessage(hwndFoundWindow, WM_GETTEXT, 5000, (LPARAM)winTxt);

  SetDlgItemText(hwndDialog, IDC_WINDOWTEXT_EDIT, winTxt);

  return lRet;
}





long RefreshWindow (HWND hwndWindowToBeRefreshed)
{
  //long lRet = 0;

  //InvalidateRect (hwndWindowToBeRefreshed, NULL, TRUE);
  //UpdateWindow (hwndWindowToBeRefreshed);
  //RedrawWindow (hwndWindowToBeRefreshed, NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);

  //return lRet;

	// Original implementation above replaced with Tom's - see:
	// http://www.codeproject.com/dialog/windowfinder.asp#xx291664xx
	long lRet = 0;

	// IMPLEMENTATION NOTES #3 - GET RID OF GARBAGE HIGHLIGHTS
	// By using parent, we get the better result in refreshing old drawing window area.
	HWND hwndParent = ::GetParent(hwndWindowToBeRefreshed);
	if (hwndParent)
	{
		hwndWindowToBeRefreshed = hwndParent;
		ATLTRACE("I am using parent. Handle:%p\n", hwndWindowToBeRefreshed);
	}

	::InvalidateRect(hwndWindowToBeRefreshed, NULL, TRUE);
	::UpdateWindow (hwndWindowToBeRefreshed);
	::RedrawWindow (hwndWindowToBeRefreshed, NULL, NULL, 
	RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASENOW | RDW_ALLCHILDREN);

	return lRet;
}





// Performs a highlighting of a found window.
// Comments below will demonstrate how this is done.
long HighlightFoundWindow (HWND hwndDialog, HWND hwndFoundWindow)
{
  HDC		hWindowDC = NULL;  // The DC of the found window.
  HGDIOBJ	hPrevPen = NULL;   // Handle of the existing pen in the DC of the found window.
  HGDIOBJ	hPrevBrush = NULL; // Handle of the existing brush in the DC of the found window.
  RECT		rect;              // Rectangle area of the found window.
  long		lRet = 0;

  // Get the screen coordinates of the rectangle of the found window.
  GetWindowRect (hwndFoundWindow, &rect);

  // Get the window DC of the found window.
  hWindowDC = GetWindowDC (hwndFoundWindow);

  if (hWindowDC)
  {
    // Select our created pen into the DC and backup the previous pen.
    hPrevPen = SelectObject (hWindowDC, g_hRectanglePen);

    // Select a transparent brush into the DC and backup the previous brush.
    hPrevBrush = SelectObject (hWindowDC, GetStockObject(HOLLOW_BRUSH));

    // Draw a rectangle in the DC covering the entire window area of the found window.
    Rectangle (hWindowDC, 0, 0, rect.right - rect.left, rect.bottom - rect.top);

    // Reinsert the previous pen and brush into the found window's DC.
    SelectObject (hWindowDC, hPrevPen);

    SelectObject (hWindowDC, hPrevBrush);

    // Finally release the DC.
    ReleaseDC (hwndFoundWindow, hWindowDC);
  }

  return lRet;
}





BOOL CALLBACK SearchWindowDialogProc
(
  HWND hwndDlg, // handle to dialog box 
  UINT uMsg, // message 
  WPARAM wParam, // first message parameter 
  LPARAM lParam // second message parameter 
)
{
  BOOL bRet = FALSE;  // Default return value.

  switch (uMsg)
  {
    case WM_INITDIALOG :
	{
	  bRet = TRUE;
	  int nState;

	  // Expanded state?
	  nState=AfxGetApp()->GetProfileInt("Window", "ExpandedState", BST_CHECKED);
	  CheckDlgButton(hwndDlg, IDC_EXPANDVIEW_CHECK, nState);
	  SetDlgSize(hwndDlg);

	  // Position
	  int x = AfxGetApp()->GetProfileInt("Window", "Left", 0),
		  y = AfxGetApp()->GetProfileInt("Window", "Top", 0),
		  cx = AfxGetApp()->GetProfileInt("Window", "Width", 389),
		  cy = AfxGetApp()->GetProfileInt("Window", "Height", 496);

	  // On Top state
	  nState=AfxGetApp()->GetProfileInt("Window", "OnTop", BST_UNCHECKED);
	  CheckDlgButton(hwndDlg, IDC_TOPMOST_CHECK, nState);
	  if(nState == BST_CHECKED)
		  SetWindowPos( hwndDlg, HWND_TOPMOST, x, y, cx, cy, SWP_SHOWWINDOW );
	  else
		  SetWindowPos( hwndDlg, HWND_NOTOPMOST, x, y, cx, cy, SWP_SHOWWINDOW );

	  break;
	}

	case WM_DESTROY :
	{
		WINDOWPLACEMENT wp;
		GetWindowPlacement(hwndDlg, &wp);
		AfxGetApp()->WriteProfileInt("Window", "Left", wp.rcNormalPosition.left);
		AfxGetApp()->WriteProfileInt("Window", "Top", wp.rcNormalPosition.top);
		AfxGetApp()->WriteProfileInt("Window", "Width", wp.rcNormalPosition.right-wp.rcNormalPosition.left);
		AfxGetApp()->WriteProfileInt("Window", "Height", wp.rcNormalPosition.bottom-wp.rcNormalPosition.top);
	}

	case WM_MOUSEMOVE :
	{
      bRet = TRUE;

	  if (g_bStartSearchWindow)
	  {
	    // Only when we have started the Window Searching operation will we 
		// track mouse movement.
	    DoMouseMove(hwndDlg, uMsg, wParam, lParam);
	  }


	  break;
	}


	case WM_LBUTTONUP :
	{
      bRet = TRUE;

	  if (g_bStartSearchWindow)
	  {
	    // Only when we have started the window searching operation will we
		// be interested when the user lifts up the left mouse button.
	    DoMouseUp(hwndDlg, uMsg, wParam, lParam);
	  }
	  break;
	}

	case WM_COMMAND :
	{
      WORD wNotifyCode = HIWORD(wParam); // notification code 
      WORD wID = LOWORD(wParam);         // item, control, or accelerator identifier 
      HWND hwndCtl = (HWND)lParam;      // handle of control 

	  if ((wID == IDOK) || (wID == IDCANCEL))
	  {
	    bRet = TRUE;
	    EndDialog (hwndDlg, wID);
	  }

	  if (wID == IDC_STATIC_ICON_FINDER_TOOL)
	  {
	    // Because the IDC_STATIC_ICON_FINDER_TOOL static control is set with the SS_NOTIFY
		// flag, the Search Window's dialog box will be sent a WM_COMMAND message when this 
		// static control is clicked.
        bRet = TRUE;
		// We start the window search operation by calling the DoSearchWindow() function.
		SearchWindow(hwndDlg);
	    break;
	  }

	  if(wID == IDC_CLIPPIE_BUTTON)
	  {
		  
		  HWND hEdWin=GetDlgItem(hwndDlg, IDC_WINDOWTEXT_EDIT);
		  SendMessage(hEdWin, EM_SETSEL, 0, -1);
		  SendMessage(hEdWin, WM_COPY, 0, 0);
	  }

	  if(wID == IDC_MOVETO_BUTTON)
	  {
		  // Get target x/y position from dialog
		  int x=GetDlgItemInt(hwndDlg, IDC_XPOS_EDIT, NULL, TRUE),
			  y=GetDlgItemInt(hwndDlg, IDC_YPOS_EDIT, NULL, TRUE);

		  // Get current placement
		  WINDOWPLACEMENT wp;
		  GetWindowPlacement(g_hwndFoundWindow, &wp);
		  int w = wp.rcNormalPosition.right-wp.rcNormalPosition.left,
			  h	= wp.rcNormalPosition.bottom-wp.rcNormalPosition.top;

		  // Adjust to desired location
		  wp.rcNormalPosition.left=x;
		  wp.rcNormalPosition.top=y;
		  wp.rcNormalPosition.right=x+w;
		  wp.rcNormalPosition.bottom=y+h;

		  // Set window placement
		  SetWindowPlacement(g_hwndFoundWindow, &wp);
	  }

	  if(wID == IDC_CENTER_BUTTON)
	  {
		  // Get current placement
		  WINDOWPLACEMENT win_wp, desk_wp;
		  GetWindowPlacement(g_hwndFoundWindow, &win_wp);
		  GetWindowPlacement(GetDesktopWindow(), &desk_wp);
		  int win_w = win_wp.rcNormalPosition.right-win_wp.rcNormalPosition.left,
			  win_h	= win_wp.rcNormalPosition.bottom-win_wp.rcNormalPosition.top,
			  desk_w = desk_wp.rcNormalPosition.right-desk_wp.rcNormalPosition.left,
			  desk_h = desk_wp.rcNormalPosition.bottom-desk_wp.rcNormalPosition.top;
		  win_wp.rcNormalPosition.left=(desk_w/2)-win_w/2;
		  win_wp.rcNormalPosition.top=(desk_h/2)-win_h/2;
		  win_wp.rcNormalPosition.right=win_wp.rcNormalPosition.left+win_w;
		  win_wp.rcNormalPosition.bottom=win_wp.rcNormalPosition.top+win_h;
		  SetWindowPlacement(g_hwndFoundWindow, &win_wp);

		  SetDlgItemInt(hwndDlg, IDC_XPOS_EDIT, win_wp.rcNormalPosition.left, FALSE);
		  SetDlgItemInt(hwndDlg, IDC_YPOS_EDIT, win_wp.rcNormalPosition.top, FALSE);
	  }

	  if(wID == IDC_RESIZE_BUTTON)
	  {
		  // Get desired width and height
		  int w=GetDlgItemInt(hwndDlg, IDC_WIDTH_EDIT, NULL, TRUE),
			  h=GetDlgItemInt(hwndDlg, IDC_HEIGHT_EDIT, NULL, TRUE);

		  // Get current placement
		  WINDOWPLACEMENT wp;
		  GetWindowPlacement(g_hwndFoundWindow, &wp);

		  // Adjust width and height to required
		  wp.rcNormalPosition.right=wp.rcNormalPosition.left+w;
		  wp.rcNormalPosition.bottom=wp.rcNormalPosition.top+h;

		  // Set window placement
		  SetWindowPlacement(g_hwndFoundWindow, &wp);
	  }

	  if(wID == IDC_TOPMOST_CHECK)
	  {
		  UINT nBtnState=IsDlgButtonChecked(hwndDlg, IDC_TOPMOST_CHECK);
		  if(nBtnState == BST_CHECKED)
			  SetWindowPos( hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW );
		  else
			  SetWindowPos( hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW );
 		  AfxGetApp()->WriteProfileInt("Window", "OnTop", nBtnState);
	  }

	  if(wID == IDC_EXPANDVIEW_CHECK)
	  {
		  UINT nBtnState=IsDlgButtonChecked(hwndDlg, IDC_EXPANDVIEW_CHECK);
		  SetDlgSize(hwndDlg);
		  AfxGetApp()->WriteProfileInt("Window", "ExpandedState", nBtnState);
	  }
	  if(wID == IDC_CAPTURE_BUTTON)
	  {
		  // Minimise ourself so we don't get in the capture
		  ShowWindow(hwndDlg, SW_HIDE);
		  ::Beep(2400, 60);

		  HDC hdc, hdcMem;
		  HBITMAP hBitmap;
		  hdc=GetDC(HWND_DESKTOP);
		  hdcMem=CreateCompatibleDC(hdc);
		  RECT rect;
		  GetWindowRect(g_hwndFoundWindow, &rect);
		  hBitmap=CreateCompatibleBitmap(hdc, rect.right-rect.left, rect.bottom-rect.top);
		  if(hBitmap)
		  {

			  SelectObject(hdcMem, hBitmap);
			  
			  BitBlt(hdcMem, 0, 0, rect.right-rect.left, rect.bottom-rect.top, hdc, rect.left, rect.top, SRCCOPY);
			  OpenClipboard(NULL);
			  EmptyClipboard();
			  SetClipboardData(CF_BITMAP, hBitmap);
			  CloseClipboard();
			  DeleteDC(hdcMem);
			  ReleaseDC(g_hwndFoundWindow,hdc);

			  ::Beep(1200, 60);
		  }
		  // Restore ourself
		  ShowWindow(hwndDlg, SW_SHOW);
	  }

	  // Clicked on Hyperlink to http://www.Powerprogrammer.co.uk?
	  if(wID == IDC_LINK_STATIC)
	  {
			if( ShellExecute(NULL, "open", "http://www.Powerprogrammer.co.uk", NULL, NULL, SW_SHOW) <= (HINSTANCE)32)
			{
				AfxMessageBox("An error occurred accessing the PowerProgrammer URL!");
			}
	  }
	  break;
	}

	default :
	{
	  bRet = FALSE;
	  break;
	}
  }

  return bRet;
}


void SetDlgSize(HWND hwndDlg)
{
	WINDOWPLACEMENT dlgwp;
	GetWindowPlacement(hwndDlg, &dlgwp);
	CRect rect;

	UINT nBtnState=IsDlgButtonChecked(hwndDlg, IDC_EXPANDVIEW_CHECK);
	if(nBtnState == BST_CHECKED) // Expanded view
	{
		// Get window placement of bottom groupbox, which is the marker for the expanded view
		GetWindowRect(GetDlgItem(hwndDlg, IDC_DETAILS_STATIC), &rect);
		dlgwp.rcNormalPosition.bottom=rect.bottom+8;
		SetWindowPlacement(hwndDlg, &dlgwp);
	}
	else // Shrunk view
	{
		// Get window placement of window text static, which is the marker for the expanded view
		GetWindowRect(GetDlgItem(hwndDlg, IDC_WINTXT_STATIC), &rect);
		dlgwp.rcNormalPosition.bottom=rect.top+2;
		SetWindowPlacement(hwndDlg, &dlgwp);
	}
	AfxGetApp()->WriteProfileInt("Window", "ExpandedState", nBtnState);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
CEO Data Perceptions
United Kingdom United Kingdom
Software designer and developer of Prophecy, a multi-user solution for sales forecasting and the Software Update Wizard, an automatic updates component that lets software developers add automatic updates to their Windows applications with a single line of code and which supports automatic updates, even where the logged in user does not have (write) rights to Program Files etc. folders.

I started working life as full time sales forecaster in the CPG sector. Transitioned to IT as I had an interest in software development and felt combining this with my previous business experience would be good.

After many years working for a company I developed Prophecy as a spare-time project and became self-employed in 1998, with Prophecy and the Software Update Wizard as my sole sources of income. It's been an interesting and challenging ride!

Comments and Discussions