OCX Controls & software technologies

 


Precision Display Capture

Copyright (c) © 2002 by Daniele Paolo Scarpazza;
Portions based upon paintlib, copyright (c) © 1996-1999 by Ulrich von Zadow


Download free sample VC++ project with sources (49k)


[top] [overview] [quick start] [trial vs full] [properties] [methods] [scrollbar usage]

Overview

[top] [overview] [quick start] [trial vs full] [properties] [methods] [scrollbar usage]


Purpose
Precision Level Indicator is a powerful OCX control which can be used to capture the screen contents. It allows a wide range of graphic manipulations and saves the result in the following formats BMP (Windows Bitmap), TIFF, JPEG, GIF, PNG.
Optimization
Precision Display Capture was written entirely in C++ and is composed of strongly optimized code, the distributed OCX file only contains the essential code needed to perform the required features. There are no memory leaks, all the allocated memory and graphic resources are gracefully released. The only required libraries are the MFC and MSVCRT dll that are shipped with every version of Microsoft Windows. You do not need any additional libraries.
High flexibility
Precision Display Capture can be used in silent or in interactive mode (see documentation below for details, it can capture all the screen or a single window, selectable by title, class name or both. The window to be captured can be raised to top level.
Any special requirement ?
If you are developing an application and found Precision Display Capture is nearly perfect for you needs except for small details ? Please feel free to contact us: let's talk about it!
Documentation
All the documentation you may need on Precision Display Capture is on line !


Quick start


[top] [overview] [quick start] [trial vs full] [properties] [methods] [scrollbar usage]

You can start using Precision Display Capture incredibly quickly: the control default factory parameters are already sensible for a basic use, you have only got to:

Now you can take a more accurate look at properties and methods to fully exploit the power of Precision Display Capture.


Trial version vs. Full version


[top] [overview] [quick start] [trial vs full] [properties] [methods] [scrollbar usage]

In trial version a nag window will appear every time a capture is performed and the save methods are disabled. In trial version the SetLicense() method does nothing and always returns FALSE.

The complete version is available online as soon as you complete the online payment transaction, you also will receive your license code with your copy of the control. The complete version requires to be unlocked with this license number, by calling SetLicense() as described below. The control will not do any capture until you set a valid license number.


Properties


[top] [overview] [quick start] [trial vs full] [properties] [methods] [scrollbar usage]

Properties can also be set at design time, by using the property inspection and modification windows that your development environment makes available.

BackColor
Domain:
any color
Default value:
depends on your development environment, usually the same as system color for MDI window background
Meaning:
this is the color used to fill the control space not used by the captured image. When there is no captured image (because the screen has not been captured yet or the Trash() method has just been invoked) this color fills the whole control. When the ShowImage property is set to false, captured images are never shown, and the control always appears a simple rectangle filled with this color.
ShowImage
Domain:
true, false
Default value:
true
Meaning:
this flag indicates whether captured images have to be shown inside the control's rectangle or not. Set this flag to true, possibly resizing the control dynamically according to the container size (if the container is resizable) if you want to offer capture and view features to the user. Set this flag to false, possibly setting the size of the control to zero if you just want to add silent screen capture features to your application.
JPEGHorizontalRes
Domain:
any integer
Default value:
96
Meaning:
horizontal resolution expressed in DPI saved in JPEG information fields. This value is actually used only if the SaveJpeg() method is invoked. The value has no practical effects on the control's behaviour, but it can be used by other programs which open the resulting JPEG file. This value is used only by the SaveJpeg() method.
JPEGOptimizeCoding
Domain:
true, false
Default value:
true
Meaning:
this flag enables or disables the generation of optimal Huffmann coding tables. This value is used only by the SaveJpeg() method.
JPEGSaveQuality
Domain:
0 ... 100
Default value:
100
Meaning:
indicates the compression quality on a scale from 0 to 100. Reduce this number if you want a smaller resulting file. This value is used only by the SaveJpeg() method.
JPEGSmoothingFactor
Domain:
0 ... 100
Default value:
0
Meaning:
indicates the smoothing factor on a scale from 0 to 100. A value of 0 means that smoothing is disabled. This value is used only by the SaveJpeg() method.
JPEGVerticalRes
Domain:
any integer
Default value:
96
Meaning:
vertical resolution expressed in DPI saved in JPEG information fields. This value is actually used only if the SaveJpeg() method is invoked. The value has no practical effects on the control's behaviour, but it can be used by other programs which open the resulting JPEG file. This value is used only by the SaveJpeg() method.
RaiseWindowBeforeCapture
Domain:
false, true
Default value:
true
Meaning:
this flag indicates whether a window is to be brought to the top of screen Z-order before capturing it. This flag has only effect when calling CaptureWindowBy...() methods, and has no effects on the behavior of the Capture() method. This value is used only by the SaveJpeg() method.


Methods


[top] [overview] [quick start] [trial vs full] [properties] [methods] [scrollbar usage]

bool BlackAndWhite()
Parameters:
none.
Return value:
true if the image was successfully converted to grayscale,
false if some error occured.
Meaning:
call this method to convert the currently captured image to grayscale.
bool Capture()
Parameters:
none.
Return value:
true if screen was successfully captured,
false if some error occured.
Meaning:
call this method to capture the whole screen contents. The image is captured at 24 bit color depth. If you save the image without calling Quantize(), image is saved at 24 bit color depth. Quantize() can be used to save space by reducing color depth to 8 bits. Image manipulation functions cannot be used after quantization is performed, therefore quantize the image if desired only as last operation before saving.
bool CaptureWindowByClass(string ClassName)
bool CaptureWindowByTitle(string WindowTitle)
bool CaptureWindowByClassAndTitle(string ClassName, string WindowTitle)
bool CaptureWindowByHandle(long WindowHandle)
Parameters:
ClassName is the class name of the desired window, WindowTitle is the title of desired window, WindowHandle is the handle of desired window.

Return value:
true if the desired window was successfully found and captured, false if some error occured.
Meaning:
call this method to capture the contents of a single window. The window can be selected by providing its window handle, its title, or its class name. Title and class name can be provide at the same time. Choose the method that best fits your needs. Please note that class name and window title must be specified exactly. The matching algorithm is case insensitive, and it will not work if you provide partial strings. Please note that here, the term 'class' has nothing to do with C++ classes. A window class is a registered window type. To discover which window class a window has, use the Spy++ program provided with Microsoft Visual Studio or the WinSight utility provided with Borland Languages.

In Spy++, for every window, its handle is reported (in hexadecimal notation), then its window title in quotes, then its class.

In Winsight, for every window, its handle is reported in hexadecimal notation, its class name in braces and its window title in quotes.

The following functions internally call the FindWindow() Windows' API.
CaptureWindowByClass(ClassName) -> FindWindow(ClassName,NULL)
CaptureWindowByTitle(WindowTitle) -> FindWindow(NULL,WindowTitle)
CaptureWindowByClassAndTitle(ClassName,WindowTitle) -> FindWindow(ClassName,WindowTitle)

(The following documentation comes from FindWindow() documentation, Microsoft MSDN) The FindWindow function retrieves a handle to the top-level window whose class name and window name match the specified strings. This function does not search child windows. This function does not perform a case-sensitive search.

HWND FindWindow(LPCTSTR lpClassName,  // pointer to class name
                LPCTSTR lpWindowName  // pointer to window name
               );
         
Parameters
lpClassName
Pointer to a null-terminated string that specifies the class name or is an atom that identifies the class-name string. If this parameter is an atom, it must be a global atom created by a previous call to the GlobalAddAtom function. The atom, a 16-bit value, must be placed in the low-order word of lpClassName; the high-order word must be zero.
lpWindowName
Pointer to a null-terminated string that specifies the window name (the window's title). If this parameter is NULL, all window names match.
bool Contrast(double Factor, long offset)
Parameters:
Factor is a valid real number and indicates the slope of the contrast function;
offset goes from 0 to 255 and indicates intensity at which the color stays the same.
Return value:
true if the image contrast was successfully adjusted,
false if some error occured.
Meaning:
this method enhances or reduces the image contrast using a linear mapping between input and output. The zero point (i.e., the intensity that is neither enhanced nor reduced) has to be provided via the offset argument. The contrast filter is lowers all intensity values below the given threshold, and it raises them beyond. Most applications position the threshold at 50 % (i.e., the actual value for offset is 128). This does not always yield the best results, especially if you have an unbalanced dark/light ratio of pixels. The best you can do here is play around with the threshold. With offset 128 and Factor 1, the image stays unchanged.
bool Crop(long Left, long Top, long Right, long Bottom)
Parameters:
Left and Top are respectively the x and y coordinate of the top-left corner of the cropping rectangle,
Right and Bottom are respectively the x and y coordinate of the bottom-right corner of the cropping rectangle.
Return value:
true if the cropping was completed successfully,
false if the cropping could not be completed due to missing captured image or wrong coordinated.
Meaning:
call this method to crop a given rectangle of the captured image. Make sure that the cropping rectangle is valid by comparing the coordinates with values returned by GetCaptureWidth() and GetCaptureHeight().
bool EnableHorizontalScrollBar()
Parameters:
none.
Return value:
true if the captured image has a width which is larger than the width of the control, therefore the container should enable a horizontal scrollbar to let the user scroll the view.
This method returns false when there is no captured image.
Meaning:
it is your responsibility to call this method whenever the control is resized or its contents (the captured image) have changed their size.
Warning:
please see the paragraph dedicated to scrollbar usage and the implementation of CTryDisplayCaptureDlg::CheckScrollBars() in file DisplayCaptureCtl.cpp of the attached example application.
bool EnableVerticalScrollBar()
Parameters:
none.
Return value:
true if the captured image has a height which is larger than the height of the control, therefore the container should enable a vertical scrollbar to let the user scroll the view. This method returns false when there is no captured image.
Meaning:
it is your responsibility to call this method whenever the control is resized or its contents (the captured image) have changed their size.
Warning:
please see the paragraph dedicated to scrollbar usage and the implementation of CTryDisplayCaptureDlg::CheckScrollBars() in file DisplayCaptureCtl.cpp of the attached example application.
long GetCaptureHeight()
long GetCaptureWidth()
Parameters:
none.
Return value:
the height and the width respectively of the captured image, 0 if there is no captured image.
Meaning:
these methods are used to obtain the current image size. Please note that when the image is scaled, cropped or rotated, the values returned by these methods are updated accordingly.
long GetHorizontalOffset()
Parameters:
none.
Return value:
the x coordinate of the leftmost column of the image shown in the control.
Meaning:
use this method to obtain the x coordinate of the first column of the image actually and currently shown in the control, corresponding to the horizontal position set by the horizontal scrollbar handler, via the SetHorizontalScrollPos() method.
Warning:
please see the paragraph dedicated to scrollbar usage.
float GetHorizontalScrollPos()
Parameters:
none.
Return value:
the currently chosen position of the horizontal scrollbars, a floating-point number between 0 and 1.
Meaning:
this method is used to obtain the current position of horizontal scrollbar. This value makes sense only if the width of the image is larger than the width of the control, therefore the scrollbar is enabled (i.e. the EnableHorizontalScrollBar() returns true).
Warning:
please see the paragraph dedicated to scrollbar usage.
bool GetPixel(long X, long Y, short * pR, short * pG, short * pB)
Parameters:
X and Y are the coordinates of the point you want to get; make sure this coordinates are inside the current captured image;
pR, pG and pB are 32-bit pointers to 16-bit signed integers which are going to receive the red, green and blue component of the color of the selected pixel. You cannot provide null pointers. The only thing you can do if you are particularly lazy and want to get the color of a grayscale image, you can provide the same pointer three times, not a big gain.
Return value:
true if the pixel color was successfully retrieved, false otherwise, e.g. because you provided wrong coordinates or there is no captured image.
Meaning:
this method can be used to get the color of a given pixel.
long GetVerticalOffset()
Parameters:
none.
Return value:
the y coordinate of the topmost column of the image shown in the control.
Meaning:
use this method to obtain the y coordinate of the first row of the image actually and currently shown in the control, corresponding to the vertical position set by the vertical scrollbar handler, via the SetVerticalScrollPos() method.
Warning:
please see the paragraph dedicated to scrollbar usage.
float GetVerticalScrollPos()
Parameters:
none.
Return value:
the currently chosen position of the vertical scrollbars, a floating-point number between 0 and 1.
Meaning:
this method is used to obtain the current position of vertical scrollbar. This value makes sense only if the height of the image is larger than the height of the control, therefore the scrollbar is enabled (i.e. the EnableVerticalScrollBar() returns true).
Warning:
please see the paragraph dedicated to scrollbar usage.
bool Invert()
Parameters:
none.
Return value:
true if the image was successfully inverted,
false if some error occured.
Meaning:
call this method to invert the image colors (e.g. black becomes white and viceversa, red becomes cyan and viceversa, green becomes magenta and viceversa, blue becomes yellow and viceversa, and so on).
bool Lightness(long Lightness)
Parameters:
Lightness, goes from -100 to +100.
Return value:
true if the image lightness was successfully adjusted,
false if some error occured.
Meaning:
call this method to adjust the image lightness. Calling this method with a positive value causes a lighter image; calling this method with a negative value causes a darker image; calling this method with 0 leaves the image unchanged.
Important:
do NOT use this function after quantizing the image.
bool Quantize(short Palette, short Type)
Parameters:
Palette indicates how the palette of the quantized image is formed; it can assume one of the following values:
0 Median Cut
1 Popularity Sort
2 Use Default Palette

Type indicates which type of dithering is used; it can assume one of the following values:
0 No dithering
1 Ordered Dithering
2 Floyd-Steinberg Dithering

Return value:
true if the image lightness was successfully quantized,
false if some error occured.
Meaning:
Returns an 8 bpp bitmap containing a best-fit representation of the source 32 bpp bitmap. The palette formation algorithm and the dithering method can be selected via the function's arguments.
Important:
Image are captured at 24 bit color depth. If you save the image without calling Quantize(), images are saved at 24 bit color depth. Quantize() can be used to save space by reducing color depth to 8 bits. Image manipulation functions cannot be used after quantization is performed, therefore quantize the image if desired only as last operation before saving.
bool RChannel()
bool GChannel()
bool BChannel()
Parameters:
none.
Return value:
true if the image was successfully processed,
false if some error occured.
Meaning:
call this method to extract the desired color channel from the image. The resulting image is a greyscale image in which for each pixel the brightness is equal to the value of the red/green/blue channel for the same pixel in the original image.
bool Resize( long NewWidth, long NewHeight)
bool ResizeBox( long NewWidth, long NewHeight, double Radius)
bool ResizeHamming( long NewWidth, long NewHeight, double Radius)
bool ResizeGaussian( long NewWidth, long NewHeight, double Radius)
Parameters:
NewWidth and NewHeight are the resizing dimensions,
Radius is the parameter for the algorithm applied after resizing.
Return value:
true if the method executes successfully,
false otherwise, for example if there is no captured image.
Meaning:
this method is used to dispose of the current captured image (if any). The memory occupied by the previously captured image is released and the control client area is filled with the background color. Resize() uses a bilinear interpolation algorithm, the other methods do resizing and then apply respectively a Box, a Hamming and a Gaussian blur filter.
bool Rotate(double Angle, short R, short G, short B)
Parameters:
Angle is a double-precision floating-point number containing the desired rotation angle expressed in radians counterclockwise (an angle of ninety degrees correspond to greek pi/4 radians = 3.1415... / 4 = 0.785... radians). R, G, B specify the color used to fill the empty pixels that appear when you rotate a rectangular image.
Return value:
true if the image was successfully rotated, false otherwise.
Meaning:
this method can be used to rotate the captured image.
bool SaveBmp(string Filename)
bool SaveJpeg(string Filename)
bool SavePng(string Filename)
bool SaveTiff(string Filename)
Parameters:
none.
Return value:
true if the image was successfully saved, false otherwise.
Meaning:
this method is used to activate the full-version control. These methods save the image file the full file name, including extension.
Warning:
these methods are disabled in the trial version of the control and always return false.
bool SetHorizontalScrollPos(float Position)
Parameters:
Position is a floating-point number between 0 and 1.
Return value:
true if there is a captured image, false otherwise.
Meaning:
this method is used to instruct the control to scroll horizontally the displayed image to the desired position. This method should be invoked inside your horizontal scrollbar event handler, in a way similar to the one illustrated in the provided example, file TryDisplayCaptureDlg.cpp, method CTryDisplayCaptureDlg::OnHScroll(). This method actually affects the way the captured image is displayed only if the image is wider than the horizontal size of the control; if the displayed image is narrower than the horizontal size of the control, the value that you provide is anyway retained and kept for later use, but not used, and the captured image is always aligned with the left edge of the control bounding box, while the remaining space is filled with the background color. Examples:
  • SetHorizontalScrollPos(0) shows the leftmost portion of the bitmap; should be called when the horizontal scrollbar is at its leftmost position;
  • SetHorizontalScrollPos(1) shows the rightmost portion of the bitmap; should be called when the horizontal scrollbar is at its rightmost position;
  • SetHorizontalScrollPos(0.5) shows the middle portion of the bitmap; should be called when the horizontal scrollbar is at the middle of its range;
bool SetLicense(long LicenseNumber)
Parameters:
LicenseNumber, a long integer number which represent your license number.
Return value:
a boolean value that represents the result of the authentication.
Meaning:
this method is used to activate the full-version control. You should call this method before calling any other method, passing the license number you obtained at purchase time as LicenseNumber parameter, otherwise the control will not draw itself on the screen.
Attention:
you do not need to use this method using the trial version of the control.
bool SetPixel(long X, long Y, short R, short G, short B)
Parameters:
X and Y are long integer numbers representing the coordinates of the point you want to change,
R, G and B are the red, green and blue components of the color you want to set, each ranging from 0 to 255.
Return value:
true if the point was successfully colored with the given color,
false otherwise, for example if there is no captured image or the given coordinates are incorrect.
Meaning:
this method is used to set the color of a pixel. By using this method you can implement a simple paint or image-manipulation program. The provided example illustrates how to use this method to realize a simple red brush controlled by the mouse, please see file TryDisplayCaptureDlg.cpp, method CTryDisplayCaptureDlg::OnMouseMoveCtl, last section.
bool SetVerticalScrollPos(float Position)
Parameters:
Position is a floating-point number between 0 and 1.
Return value:
true if there is a captured image,
false otherwise.
Meaning:
this method is used to instruct the control to scroll vertically the displayed image to the desired position. This method should be invoked inside your vertical scrollbar event handler, in a way similar to the one illustrated in the provided example, file TryDisplayCaptureDlg.cpp, method CTryDisplayCaptureDlg::OnVScroll(). This method actually affects the way the captured image is displayed only if the image is higher than the vertical size of the control; if the displayed image is shorter than the vertical size of the control, the value that you provide is anyway retained and kept for later use, but not used, and the captured image is always aligned with the top edge of the control bounding box, while the remaining space is filled with the background color.

Examples:

  • SetVerticalScrollPos(0) shows the topmost portion of the bitmap; should be called when the vertical scrollbar is at its topmost position;
  • SetVerticalScrollPos(1) shows the bottom portion of the bitmap; should be called when the vertical scrollbar is at its bottom position;
  • SetVerticalScrollPos(0.5) shows the middle portion of the bitmap; should be called when the vertical scrollbar is at the middle of its range;
void Trash()
Parameters:
none.
Return value:
none.
Meaning:
this method is used to dispose of the current captured image (if any). The memory occupied by the previously captured image is released and the control client area is filled with the background color.


How to add scrollbars


[top] [overview] [quick start] [trial vs full] [properties] [methods] [scrollbar usage]

If you enable the ShowImage flag, the user will be able to show the results of the capture in an interactive way. This means that your application could follow the mouse movements over the image contained in the control and act on it. Or it will be possible to scroll the whole image inside the control if the control's bounding box is smaller than it.

In order to enable scrolling, your application must provide scrollbars, and provide a sort of bi-directional communication between the control and the application about the scrollbar status. In other words the control will be able to tell to the application whether to enable the horizontal and vertical scrollbars (and this happens respectively when the image is wider than the control and when the image is taller than the control), and the application will instruct the control to scroll its contents when the user acts on the scrollbar.

The steps are described here for the Visual C++ development environment, but could be done in any other language with minor modifications.
Step 1: place the Precision Display Capture control, an horizontal scrollbare and a vertical scrollbar onto your dialog window,
Step 2: invoke ClassWizard (Ctrl+W), select the 'Member Variables' tab, then, for every scrollbar, click on its ID and on the 'Add Variable' button. Select 'Control' in the 'Category' dropdown, use m_sbv and m_sbh as variable names;
Step 3: go to the 'Message maps' tab of ClassWizard and in the 'Object IDs' list select the C++ class of the dialog window to which you added the control and the scrollbars. Add a function to the messages WM_INITDIALOG, WM_HSCROLL and WM_VSCROLL.
Step 4: add the following definitions at the beginning of your .cpp file containing the dialog implementation:
        #define WHOLE 100
        #define PAGE   10
        #define LINE    1
        
then add the following statements to your OnInitDialog function:
        m_sbh.SetScrollRange(0,WHOLE);
        m_sbv.SetScrollRange(0,WHOLE);
	
Step 5: In both your OnHScroll and OnVScroll add the following code fragment:
        int iPos=pScrollBar->GetScrollPos();	
        switch(nSBCode)
        {
         case SB_TOP:            iPos = 0;                                            break;
         case SB_THUMBPOSITION:
         case SB_THUMBTRACK:     iPos = nPos;                                         break;
         case SB_BOTTOM:         iPos = WHOLE;                                        break;
         case SB_ENDSCROLL:                                                           break;
         case SB_PAGEDOWN:       if(iPos < WHOLE-PAGE) iPos+=PAGE; else iPos = WHOLE; break;
         case SB_LINEDOWN:       if(iPos < WHOLE)      iPos+=LINE; else iPos = WHOLE; break;
         case SB_LINEUP :        if(iPos > PAGE)       iPos-=PAGE; else iPos = 0;     break; 
         case SB_PAGEUP :        if(iPos > 0)          iPos-=LINE; else iPos = 0;     break;
        }
        pScrollBar->SetScrollPos(iPos);		
        

At the end of your OnVScroll add the following code fragment:
    m_cap.SetVerticalScrollPos(iPos/(float)WHOLE); 

and at the end of OnHScroll add:
    m_cap.SetHorizontalScrollPos(iPos/(float)WHOLE); 

To learn more on the usage of scrollbars, please see file TryDisplayCaptureDlg.cpp of the sample Visual C++ project file. Please note that, due to scrolling, the image-coordinates of the image pixel currently under the mouse are different from the coordinates of the same pixel expressed in the client rectangle reference system. In particular you have to subtract (or add) the current vertical and horizontal offsets, as in the following code fragment:

        void CTryDisplayCaptureDlg::OnMouseMoveCtl(short Button, short Shift, long X, long Y) 
        {
         X += m_cap.GetHorizOffset();
         Y += m_cap.GetVertOffset();
         m_strPosition.Format("(%i,%i)", X, Y);
         ...
        }