Recent

Author Topic: WinAPI - examples - post 8  (Read 2077 times)

440bx

  • Hero Member
  • *****
  • Posts: 2468
WinAPI - examples - post 8
« on: March 20, 2021, 08:37:16 pm »


This post includes examples for a number of API functions and how they can be used to prevent/eliminate flicker.  This is the second and last post related to preventing/eliminating flicker.  Some of the examples are not directly about flicker, they are included because they are used in other examples that are about reverting/eliminating flicker.

The examples are:


WinAPI - ExtTextOut                         (ExtTextOut in folder Ex1)
WinAPI - CopyRect             
WinAPI - Rectangle             
WinAPI - WM_GETMINMAXINFO     


WinAPI - ExtTextOut                         (ExtTextOut in folder Ex2)
WinAPI - GetDC                 
WinAPI - ReleaseDC             
WinAPI - OffsetRect           
WinAPI - CopyRect             
WinAPI - InflateRect           
WinAPI - InvalidateRect       
WinAPI - HeapAlloc             
WinAPI - GetCursorPos         
WinAPI - WindowFromPoint       
WinAPI - IsWindow             
WinAPI - UpdateWindow         
WinAPI - SetBkColor           


WinAPI - InvalidateRect                    (in InvalidateRect)
WinAPI - GetWindowRect         
WinAPI - OffsetRect           
WinAPI - GetDC                 
WinAPI - GetDCEx               
WinAPI - SetROP2               
WinAPI - Rectangle             
WinAPI - ReleaseDC             
WinAPI - SetRectEmpty         
WinAPI - HeapAlloc             
WinAPI - CreatePen             
WinAPI - PostMessage           
WinAPI - SendMessage           
WinAPI - SetCapture           
WinAPI - ReleaseCapture       
WinAPI - SetWindowPos         
WinAPI - LockWindowUpdate     
WinAPI - UpdateWindow         
WinAPI - GetCursorPos         
WinAPI - IsWindow             
WinAPI - GetParent             
WinAPI - WindowFromPoint       
WinAPI - UpdateWindow         


WinAPI - GetCharacterPlacement    (GetCharacterPlacement in folder Ex1)
WinAPI - ExtTextOut           
WinAPI - RtlZeroMemory         


WinAPI - GetCharacterPlacement    (GetCharacterPlacement in folder Ex2)
WinAPI - ExtTextOut           
WinAPI - RtlZeroMemory         


WinAPI - BitBlt                                 (in BitBlt)
WinAPI - LoadBitmap           
WinAPI - CreateCompatibleDC   
WinAPI - GetObject             
WinAPI - DeleteDC             


WinAPI - StretchBlt                          (in StretchBlt)
WinAPI - LoadBitmap           
WinAPI - CreateCompatibleDC   
WinAPI - GetObject             
WinAPI - DeleteDC             


WinAPI - CreateCompatibleBitmap(in CreateCompatibleBitmap)
WinAPI - CreateCompatibleDC   
WinAPI - DeleteDC             
WinAPI - CreateFont           
WinAPI - MoveWindow           
WinAPI - GetSysColor           
WinAPI - BitBlt               


WinAPI - SelectClipRgn                  (in SelectClipRgn)
WinAPI - CreateFont           
WinAPI - GetDC                 
WinAPI - ReleaseDC             
WinAPI - BeginPath             
WinAPI - EndPath               
WinAPI - PathToRegion         
WinAPI - GetRgnBox             
WinAPI - OffsetRgn             
WinAPI - ExtSelectClipRgn     
WinAPI - SelectClipRgn         


WinAPI - CallWindowProc               (in ColorMixer)
WinAPI - CopyRect             
WinAPI - CreateSolidBrush     
WinAPI - CreateRectRgnIndirect
WinAPI - ExtSelectClipRgn     
WinAPI - SelectClipRgn         
WinAPI - ExtTextOut           
WinAPI - FrameRect             
WinAPI - GetWindowLongPtr     
WinAPI - InvalidateRect       
WinAPI - MoveWindow           
WinAPI - Rectangle             
WinAPI - SetFocus             
WinAPI - SetScrollInfo         
WinAPI - SetScrollPos         
WinAPI - SetTextColor         
WinAPI - TextOut               
WinAPI - WM_CTLCOLORSCROLLBAR 
WinAPI - WM_GETMINMAXINFO     
WinAPI - WM_VSCROLL           


Continued on next post...
« Last Edit: March 20, 2021, 09:15:14 pm by 440bx »
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

440bx

  • Hero Member
  • *****
  • Posts: 2468
Re: WinAPI - examples - post 8
« Reply #1 on: March 20, 2021, 08:46:43 pm »
Continued from previous post ...


WinAPI - ExtTextOut            (example 1 of 2)

This first example of the ExtTextOut API is similar to the FlickerMin example in post 7 (see post 7 for the source.)

It demonstrates ExtTextOut's ability to clip text to a rectangle.  It clears the background areas as necessary when processing the WM_PAINT message instead of letting the default window procedure clear it when processing the WM_ERASEBKGND.  It produces less flicker than FlickerMin because it uses a smaller font.  (NOTE: the flicker is easier to see when resizing the window horizontally only.)

Also note that it does not specify CS_HREDRAW nor CS_VREDRAW in the class styles, instead it invalidates the client area, _without erasing it_ when processing the WM_SIZE message.

The rectangle coordinates used to erase the background can be output onto a console by recompiling the program with the "DEBUG" define active.  This is useful to see/verify the coordinates of the background rectangles that are erased when painting.

Use the options under the "ExtTextOut" menu to control the clipping of text.

It also demonstrates how to process the WM_GETMINMAXINFO to control the minimum width and height of the window.





WinAPI - InvalidateRect       

Carefully controlling which parts of the client area are invalidated can significantly reduce flicker.

This example shows the effect of invalidating the entire client area compared to the effect of invalidating a smaller area that is the one that needs to be updated.  When "Invalidate entire area" is selected in the "InvalidateRect" menu, the amount of flicker will be very noticeable.  When "Invalidate coordinate area" is selected, the amount of flicker is drastically reduced and confined to a much smaller area.

The flicker left is due to the use of TextOut and specifying TRUE in the call to InvalidateRect when processing the WM_MOUSEMOVE message:
Code: Pascal  [Select][+][-]
  1.       InvalidateRect(Wnd, @UpdateRect, TRUE);
This causes the coordinate area to be erased thus showing a clear background before TextOut outputs the new coordinate values.

NOTE: All the coordinates shown are relative to the _client area_ of the respective windows.






WinAPI - ExtTextOut            (example 2 of 2)

This example is the InvalidateRect example but with all flicker removed.  The absence of flicker is due to the different way the coordinate rectangle is invalidated when processing the WM_MOUSEMOVE message:
Code: Pascal  [Select][+][-]
  1.       InvalidateRect(Wnd, @CoordinateRect, FALSE);  { NO background erase!    }
  2.  
  Note, that InvalidateRect is instructed not to require the background to be erased by specifying FALSE (third parameter.)  This combined with the fact that ExtTextOut repaints the background and the text in one operation eliminates all flicker in the coordinates area.

However, it is still possible to see some occasional flicker when first pressing the left mouse button.  The default processing of the WM_LBUTTONDOWN message Invalidates the entire client area with the statement:
Code: Pascal  [Select][+][-]
  1.           InvalidateRect(Wnd, nil, TRUE);
This will cause some flicker to be noticeable if the left mouse button is very quickly pressed down and released (about 7 to 10 times per seconds) for a few seconds (5 seconds should normally enough.)

That occasional flicker can be removed by selecting "Exclude bottom line from invalidated area" which will cause the call to InvalidateRect to be:
Code: Pascal  [Select][+][-]
  1.       MenuItemState := GetMenuState(GetMenu(Wnd), IDM_EXCLUDE, MF_BYCOMMAND);
  2.  
  3.       case MenuItemState <> 0 of
  4.         true  :
  5.         begin
  6.           { menu item is checked, exclude the bottom of the client area       }
  7.  
  8.           GetClientRect(Wnd, ClientRect);
  9.  
  10.           ClientRect.Bottom := ClientRect.Bottom - Exclude;
  11.           InvalidateRect(Wnd, @ClientRect, TRUE);
  12.         end;
thus excluding the area where the ExtTextOut definition is drawn causing all flicker to be eliminated.


NOTE: the ExtTextOut attachment contains both examples.


Continued on next post ...
« Last Edit: March 20, 2021, 09:11:23 pm by 440bx »
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

440bx

  • Hero Member
  • *****
  • Posts: 2468
Re: WinAPI - examples - post 8
« Reply #2 on: March 20, 2021, 08:52:16 pm »
Continued from previous post ...


WinAPI - GetCharacterPlacement (example 1 of 2)

ExtTextOut is a powerful function and when it is combined with GetCharacterPlacement its power surfaces.

GetCharacterPlacement has a large number of options and the two examples presented here do not do it justice but, will give a _small_ taste of what it enables ExtTextOut to do.    For all the available options, please see MSDN.

This example simply takes a string and uses GetCharacterPlacement to determine how to "spread" it over a specified number of pixels.  GetCharacterPlacement returns an array of inter-character distances that are used by ExtTextOut to display the string.






WinAPI - GetCharacterPlacement (example 2 of 2)

The first example above is a bit deceiving.  The same example using a slightly different criteria allows converting a proportionally spaced font into a fixed space font.  Normally, such a conversion is undesirable because the additional inter-character whitespace is unsightly but, there are exceptions and, this example shows one of them.

One such case is when outputting the value of registers in a debugger.  Most fixed fonts have digits that are not particularly easy to read whereas proportional fonts usually have aesthetically pleasing and easy to read digits.

This example turns any hex number consisting of digits 0-F from proportional to fixed and, for comparison, outputs them as they would in their proportional state on the right hand side and their fixed state on the left hand side.


NOTE: the GetCharacterPlacement attachment contains both examples.


Continued on next post ...
« Last Edit: March 20, 2021, 09:12:50 pm by 440bx »
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

440bx

  • Hero Member
  • *****
  • Posts: 2468
Re: WinAPI - examples - post 8
« Reply #3 on: March 20, 2021, 08:56:33 pm »
Continued from previous post ...


WinAPI - BitBlt

Likely the most common method to eliminate flicker is to paint on a bitmap then bitblt the fully drawn bitmap onto the client area.  This removes all flicker.

This example is the simplest example of BitBlt-ing meant to serve as a pre-amble to a more sophisticated example that uses it to remove flicker.

Note that this example does NOT use CS_HREDRAW nor CS_VREDRAW and that it uses a NULL_BRUSH as the background color, making it unnecessary to process the WM_ERASEBKGND to tell Windows the program erased the background when it actually didn't.  Windows will erase the background with a NULL_BRUSH which does no erasing at all.





WinAPI - StretchBlt           

StretchBlt is included in this set of examples only because it is very closely related to BitBlt.  Since they are close cousins and it is immoral to break a family, they have been kept together as they should be.


Continued on next post ...
« Last Edit: March 20, 2021, 09:13:21 pm by 440bx »
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

440bx

  • Hero Member
  • *****
  • Posts: 2468
Re: WinAPI - examples - post 8
« Reply #4 on: March 20, 2021, 09:00:47 pm »
Continued from previous post ...


WinAPI - CreateCompatibleBitmap

This example demonstrates double buffering.  The top part of the window is drawn with TextOut (and optionally ExtTextOut by re-compiling - see source) thus causing flicker while, the bottom part of the window is first drawn on a bitmap then BitBlt-ed onto the bottom half of the window. The result is that the bottom part of the window is totally flicker free.

To really appreciate the difference, resize the window.  When resizing, the top part of the window will flicker significantly while the bottom part won't flicker at all.





WinAPI - SelectClipRgn         

This example demonstrates how to use regions to eliminate flicker.  Note that it does NOT use double buffering, only regions.

It creates a region that is excluded from the "paintable" region when drawing the background gradient.  After the background gradient has been painted then that region is made the "paintable" region and a different gradient is painted in it.

The inclusion and exclusion of the region is controlled by the options under the "Flicker" menu.  When the region is excluded, there will be no flicker and, when it is included, flicker will be noticeable when resizing the window.


Continued on next post ...
« Last Edit: March 20, 2021, 09:14:03 pm by 440bx »
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

440bx

  • Hero Member
  • *****
  • Posts: 2468
Re: WinAPI - examples - post 8
« Reply #5 on: March 20, 2021, 09:05:03 pm »
Continued from previous post ...


Utility - ColorMixer           

This example which doubles as a simple color mixing/selection utility demonstrates how to eliminate flicker using ExtTextOut, Regions and InvalidateRect.

It uses all the methods to prevent flicker except double buffering.

In addition to that, it demonstrates how to use scroll bars as controls, how to subclass a window (in this case the scroll bars), how to handle keyboard input to set and select which scroll bar has the focus, as well as, setting the numeric value for each color (use arrow keys, home/end, page up/down), and how to process the WM_GETMINMAXINFO to set the minimum, maximum and maximized sizes of a window.

Aside from the 3 scroll bars that control the settings of the Red, Green and, blue colors, there is only _one_ window.  The right and left hand side are _not_ separate windows.

The example provides the option of displaying the coordinates of the various rectangles used to eliminate flicker by enabling the SHOW_RECTANGLE_COORDINATES define.

It also allows controlling whether or not the sample text will flicker by enabling or disabling the define NO_SAMPLE_TEXT_FLICKER.

The numeric values of Red, Green and Blue shown below the scroll bars are _not_ protected against flicker.  Grabbing any of the scroll bar thumbs and moving it up and down quickly for several seconds while paying close attention to the numbers will make a very slight amount of flicker visible.  Because the amount of flicker is usually not noticeable, there is no code to prevent it.  However, the same method used to ensure the sample text does not flicker can be used with the Red, Green and Blue values for a totally flicker free utility.

ColorMixer uses its own definitions for most of the APIs it uses.  The purpose of the definitions is to minimize the number of useless hints and give better parameter names, which are used by CODETOOLS, thereby providing better guidance when programming.


Continued on next post ...
« Last Edit: March 20, 2021, 09:17:38 pm by 440bx »
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

440bx

  • Hero Member
  • *****
  • Posts: 2468
Re: WinAPI - examples - post 8
« Reply #6 on: March 20, 2021, 09:08:06 pm »
Continued from previous post ...


Dead BUG                       

There is a "dead" bug in DrawWindowFrame.  That function appears in multiple examples presented in Post 6.  The bug is as follows:
   
Code: Pascal  [Select][+][-]
  1.  
  2.   SelectObject(dc, OldPen);          { restore the original pen               }
  3.   ReleaseDC(Wnd, dc);
  4.   DeleteObject(Pen);                 { get rid of the pen                     }
  5.  
  6.   {---------------------------------------------------------------------------}
  7.   { release the window dc                                                     }
  8.  
  9.   ReleaseDC(dc, Wnd);
  10. end;
The last statement "ReleaseDC(dc, Wnd);" is erroneous for two reasons. First, the dc has already been released (just a few lines above) and second, the parameters in that call are reversed.   The erroneous statement has no effect on the proper operation of the examples in which it appears but should be removed.  Corrected code should read:
Code: Pascal  [Select][+][-]
  1.  
  2.   SelectObject(dc, OldPen);          { restore the original pen               }
  3.   ReleaseDC(Wnd, dc);
  4.  
  5.   DeleteObject(Pen);                 { get rid of the pen                     }
  6. end;

The examples affected by the above bug are :

    GetDesktopWindow.lpr
    GetShellWindow.lpr
    GetTaskmanWindow.lpr
    GetTopLevelWindow.lpr
    IsTopLevelWindow.lpr
    GetWindowTextLength.lpr

Corrected versions of the source files above are attached to this post in the file named "CorrectionsToPost6Examples.7z"  (NOTE: only examples presented in Post 6 are affected.)





Enjoy!
« Last Edit: March 20, 2021, 09:14:46 pm by 440bx »
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

Alextp

  • Hero Member
  • *****
  • Posts: 1376
    • UVviewsoft
Re: WinAPI - examples - post 8
« Reply #7 on: March 21, 2021, 06:50:00 pm »
Posted to wiki and Github.

440bx

  • Hero Member
  • *****
  • Posts: 2468
Re: WinAPI - examples - post 8
« Reply #8 on: March 21, 2021, 07:09:41 pm »
Posted to wiki and Github.
Thank you Alexey.
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

Alextp

  • Hero Member
  • *****
  • Posts: 1376
    • UVviewsoft
Re: WinAPI - examples - post 8
« Reply #9 on: September 03, 2021, 04:58:49 pm »

440bx

  • Hero Member
  • *****
  • Posts: 2468
Re: WinAPI - examples - post 8
« Reply #10 on: September 04, 2021, 09:19:16 am »
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

 

TinyPortal © 2005-2018