Return to Index
created by gbSnippets
'GDI - Graphics Device Interface
'GDI is a collection of API that supports the use of graphics and text on a video
'display or printer. Windows-based applications do not access the graphics hardware
'directly. Instead, GDI interacts with device drivers on behalf of applications.
'In general, GDI functions act on a device context (DC), which is a data structure
'consisting of a variety of objects (bitmaps, pens, brushes, ...). The data structure
'represents the drawing surface of a device, such as a display screen or printer.
'Actions taken on the DC appear immediately on the actual device.
'Most often, a device context is used to represent a specified window on the display
'screen. It might represent the entire screen, a dialog, or a control. Normally, a
'display DC represents the client area of a window, but can include the non-client area.
'From a PowerBASIC programmer's perspective, GDI repesents an SDK (API) style of
'programming. GDI and PowerBASIC GRAPHIC statements can both be used within an application
'but there are API/DDT compatibility issues to watch out for.
'Device Contexts ==========================================================================
'The key exception is device contexts. GDI and PowerBASIC GRAPHIC statements both
'create/modify Windows compatible device contexts. So a device context to a window can be
'operated on by using GDI or DDT statements, or a combination of both. Said another way,
'the handle of a device context can be used interchangeably with both types of code.
'The several hundred GDI functions can be grouped roughly into 3 categories:
'1. Surfaces & Tools - the device context and tools for working on it
'2. Graphic - drawing/printing functions
'3. Other - bitmaps, colors, coordinates, ... (see list below)
'For each of the 3 categories, MSDN provides the following topics.
' Surfaces & Tools Graphic Messages/Operations Other
' Device Context Painting & Drawing Bitmaps
' Brushes Lines & Curves Metafiles
' Paths Filled Shapes Colors
' Pens Fonts & Text Coordinate Spaces & Transforms
' Regions Rectangle Math Multiple Monitors
' Clipping Printing & Print Spoolers
'A Quick Look at the Code ==============================================================
'Let's jump to the bottom line - code. Using GDI normally starts with getting
'a handle to the device context (DC) for a window. Then, one or more of the
'GDI API are used to draw graphics or print text onto the DC. The results appear
'immediately on the window whose DC is being used. Once drawing operations are
'completed, the handle to the DC is released.
'As a short example, here's a code snippet which gets a handle to a DC for a
'dialog, draws graphics and text on the DC, and then releases the DC handle
'(the PS variable is a data structure that is discussed in a later tutorial).
hDC = BeginPaint(hDlg, PS) 'get a handle to a dialog's DC
Ellipse hDC, 20,20,80,80 'draws a circle on the dialog surface
TextOut hDC, 100,30, " test ", 6 'prints text on the dialog surface
EndPaint hDlg, PS 'releases the handle to the dialog
'This particular example shows the drawing taking place in a Callback function
'when a %WM_Paint message is received. However, drawing operations can be performed
'at any time within an application's code. This is discussed more in later tutorials.
'In addition to the BeginPaint API, there are multiple ways to get a device context
'and of releasing the handle when drawing operations are done. These, too, are
'discussed in other GDI tutorials.
'Generally, API work with pixels. Some API use screen coordinates while
'others use window coordinates (usually client coordinates). Top/left coordinates
'are (0,0) and bottom/right coordinates are (w-1,h-1).
'Getting the of size of windows, including the desktop, is done with these API:
' API Function Arguments
' GetWindowRect hWnd, pRECT 'outside dimensions of window
' GetClientRect hWnd, pRECT 'client dimensions of window
' GetDesktopWindow <no arg> 'get hWnd of desktop
' SystemParamentersInfo SPI_GetWorkArea,0,pRECT,0 'screen size without taskbar
' GetSystemMetrics SM_CXScreen 'width of screen
' GetSystemMetrics SM_CYScreen 'height of screen
'These other API are available to convert from screen-to-window, window-to-window, and
' API Function Arguments
' ScreenToClient hWnd, pPOINT 'screen to window
' MapWindowPoints hWndFrom,hWndTo, pPOINTarray, nPointCount 'window to window (multiple points)
' ClientToScreen hWnd, pPOINT 'window to screen
'In these API, the POINT variables pass one set of coordinates and also receive the
'converted (mapped) coordinates.
'Common Data Structures ===================================================================
'These data structures are frequently used with GDI API.
Type RECT Type apiSize, Points, POINT, COORD Type POINTAPI
nLeft As Long x As Long cx As Long
nTop As Long y As Long cy As Long
nRight As Long End Type End Type
nBottom As Long
'It is not uncommon for data structures to be defined which have the same members,
'such as is the case with apiSize, Points, Point, and Coord in the example above.
'Code Example ==============================================================================
'As a preview of things to come, here are a few examples of using GDI on a dialog
'and on a control. While drawing on any surface is possible (including the desktop),
'and while drawing code can be placed anywhere within an application, it is
'recommended that the WM_Paint message be used for all drawing operations.
'This code draws on the dialog and a control. It demonstrates persistent
'graphics by using code within the WM_Paint message. It shows that painting outside
'WM_Paint is non-persistent (move a window over the graphics to see what happens).
#Compiler PBWin 9, PBWin 10
Global hDlg, hCtl, hDc as DWord, PS as PaintStruct
%ID_Control = 104
Function PBMain() As Long
Dialog New Pixels, 0, "GDI Examples",300,300,200,200, %WS_OverlappedWindow To hDlg
Control Add Button, hDlg, 102,"Draw on Dialog", 10,10,120,20
Control Add Button, hDlg, 103,"Draw on Control", 10,40,120,20
Control Add Image, hDlg, %ID_Control, "cowgirl",50,80,100,100, %WS_Border
Dialog Show Modal hDlg Call DlgProc
CallBack Function DlgProc() As Long
Select Case CB.Msg
'putting the code here makes it persistent
hDC = BeginPaint(hDlg, PS) 'get a handle to the dialog DC
Ellipse hDC, 140,30,190,70 'draws a circle on the dialog surface
EndPaint hDC, PS 'releases the handle to the dialog DC
If CB.Msg = %WM_Command AND CB.Ctl = 102 AND CB.Ctlmsg = %BN_Clicked Then
'draw on dialog - this is not persistent
hDC = GetDC(hDlg) 'get a handle to dialog DC
Ellipse hDC, 10,130,40,160 'draws a circle on the dialog surface
ReleaseDC hDlg,hDC 'releases the handle to the dialog DC
If CB.Msg = %WM_Command AND CB.Ctl = 103 AND CB.Ctlmsg = %BN_Clicked Then
'draw on control - this is not persistent
hCtl = GetDlgItem(hDlg, %ID_Control) 'get handle of control
hDC = GetDC(hCtl) 'get a handle to a control DC
Ellipse hDC, 30,30,80,80 'draws a circle on the control surface
ReleaseDC hDlg,hDC 'releases the handle to the control DC
created by gbSnippets