+ All Categories
Home > Documents > C Windows Programming Tutorial

C Windows Programming Tutorial

Date post: 24-Feb-2018
Category:
Upload: ayush-saluja
View: 230 times
Download: 0 times
Share this document with a friend

of 22

Transcript
  • 7/25/2019 C Windows Programming Tutorial

    1/22

    1 - 22

    C Windows Programming Tutorial

    {From:http://www.geocities.com/Heartland/Meadows/9818/win32tut/index.html}

    Lesson 1 - Your First windows program

    Clickhereto download the source files to this tutorial.

    Welcome to a journey in Windows programming. In this lesson, you will create your first

    windows application which will display a "Hello World" message box.

    1. If you haven't started Dev-C++ already, do so now.

    2. Select File->New Project. In the dialog box that appears, choose the project type

    as an Empty Project and name the project Lesson1. Also choose the C language.

    3.

    You land up with an empty project. Now we will set the project type to Win32GUI. This tells the compiler that the project is to be compiled as a windows GUI

    application. Press Alt+P to get the project options. Select Win32 GUI under Type.

    4. Right click Lesson1 on the Project Panel and click New Unit. A new file is

    created. Save it as lesson1.c5. Now enter the code as given below:

    http://www.geocities.com/Heartland/Meadows/9818/win32tut/index.htmlhttp://www.geocities.com/Heartland/Meadows/9818/win32tut/index.htmlhttp://www.geocities.com/Heartland/Meadows/9818/win32tut/src/lesson1.ziphttp://www.geocities.com/Heartland/Meadows/9818/win32tut/src/lesson1.ziphttp://www.geocities.com/Heartland/Meadows/9818/win32tut/src/lesson1.ziphttp://www.geocities.com/Heartland/Meadows/9818/win32tut/src/lesson1.ziphttp://www.geocities.com/Heartland/Meadows/9818/win32tut/index.html
  • 7/25/2019 C Windows Programming Tutorial

    2/22

    2 - 22

    /* Windows Programming Tutorial Series* Lesson 1 - Your first windows program* Pravin Paratey (October 08, 2002)**/#include

    int WINAPIWinMain(HINSTANCE hInst,

    HINSTANCE hPrevInstance,LPSTR lpCmdLine,

    int nCmdShow){

    MessageBox (NULL, "Hello World! This is my first WIN32 program","Lesson 1", MB_OK);

    return 0;}

    6. Press F9 to compile and run the project. You should see the following,

    Congratulations! You have just written your first windows application.

    Whoa! What just happened there?

    Letsbreak down the code.

    1. #include All Windows programs must include the header file windows.h. This file has the

    definitions of Windows system calls or the WinAPI. The WinAPI has everything

    necessary for programming under windows.

    2. WinMain (..)This is the entry point of a windows application. This is like the main() of a

    console based application. WinMain is declared as,

    int WINAPI WinMain(

    HINSTANCE hInst, /* Handle to the current instance */HINSTANCE hPrevInstance,/* Handle to the previous instance */LPSTR lpCmdLine, /* pointer to command line arguments */int nCmdShow); /* show state of the window */

    The parameters of WinMain are self-explanatory, except perhaps nCmdShow.

    nCmdShow tells you in what manner you are expected to display this window(Maximized, Minimized, etc).

  • 7/25/2019 C Windows Programming Tutorial

    3/22

    3 - 22

    We haven't used any of these parameters in this lesson, but we'll see their uses in

    the coming lessons.

    3. MessageBox(..)This is a windows function which displays a messagebox. The MessageBox

    function is declared as,

    int MessageBox(HWND hWnd, /* Handle of owner window */LPCTSTR lpText, /* Address of text in message box */LPCTSTR lpCaption,/* Address of title of message box */UINT uType); /* Style of message box */

    4. return 0This is the return value to the system.

    This brings us to the end of the first lesson. Clickhereto go to the next lesson.

    http://www.geocities.com/Heartland/Meadows/9818/win32tut/lesson2.htmlhttp://www.geocities.com/Heartland/Meadows/9818/win32tut/lesson2.htmlhttp://www.geocities.com/Heartland/Meadows/9818/win32tut/lesson2.htmlhttp://www.geocities.com/Heartland/Meadows/9818/win32tut/lesson2.html
  • 7/25/2019 C Windows Programming Tutorial

    4/22

    4 - 22

    Lesson 2 - Understanding messages and

    events

    Clickhereto download the source files to this tutorial.

    In this tutorial you will be introduced to the event-driven programming model. You will

    learn how Windows uses messages to communicate with applications, how event based

    programming works, what callback functions are, and while doing this create a basicwindows application

    Before we begin

    If you do not have the platform SDK help files (WinAPI docs) - no, they do not comewith Dev-C++ - then I suggest you do one of the following:

    1. Downloadthisfile OR2. Download the Windows platform SDK frommsdn

    .

    And so i t begins

    Create a blank windows project in Dev-C++ (In case you've forgotten how this is done,take a look at theprevioustutorial). Name it lesson2. Open a new file(Press Ctrl+N) andsave it(Ctrl+S) as main.c. Enter the following code,

    1 #include 23 HWND hwndMain; //Main window handle45 // Callback function

    http://www.geocities.com/Heartland/Meadows/9818/win32tut/src/lesson2.ziphttp://www.geocities.com/Heartland/Meadows/9818/win32tut/src/lesson2.ziphttp://www.geocities.com/Heartland/Meadows/9818/win32tut/src/lesson2.zipftp://ftp.cs.virginia.edu/pub/lcc-win32/win32hlp.exeftp://ftp.cs.virginia.edu/pub/lcc-win32/win32hlp.exeftp://ftp.cs.virginia.edu/pub/lcc-win32/win32hlp.exehttp://msdn.microsoft.com/http://msdn.microsoft.com/http://msdn.microsoft.com/http://www.geocities.com/Heartland/Meadows/9818/win32tut/lesson1.htmlhttp://www.geocities.com/Heartland/Meadows/9818/win32tut/lesson1.htmlhttp://www.geocities.com/Heartland/Meadows/9818/win32tut/lesson1.htmlhttp://www.geocities.com/Heartland/Meadows/9818/win32tut/lesson1.htmlhttp://msdn.microsoft.com/ftp://ftp.cs.virginia.edu/pub/lcc-win32/win32hlp.exehttp://www.geocities.com/Heartland/Meadows/9818/win32tut/src/lesson2.zip
  • 7/25/2019 C Windows Programming Tutorial

    5/22

    5 - 22

    6 LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);7 // Windows entry point8 int WINAPI9 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)10 {11 MSG msg; // MSG structure to store messages12 WNDCLASSEX wcx; // WINDOW class information13

    14 // Initialize the struct to zero15 ZeroMemory(&wcx,sizeof(WNDCLASSEX));16 wcx.cbSize = sizeof(WNDCLASSEX); // Window size. Must always be sizeof(WNDCLASSEX)17 wcx.style = CS_HREDRAW|CS_VREDRAW |CS_DBLCLKS ; // Class styles18 wcx.lpfnWndProc = (WNDPROC)MainWndProc; // Pointer to the callback procedure19 wcx.cbClsExtra = 0; // Extra byte to allocate following the wndclassex structure20 wcx.cbWndExtra = 0; // Extra byte to allocate following an instance of the structure21 wcx.hInstance = hInstance; // Instance of the application22 wcx.hIcon = NULL; // Class Icon23 wcx.hCursor = LoadCursor(NULL, IDC_ARROW); // Class Cursor24 wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW); // Background brush25 wcx.lpszMenuName = NULL; // Menu resource26 wcx.lpszClassName = "Lesson2"; // Name of this class27 wcx.hIconSm = NULL; // Small icon for this class2829 // Register this window class with MS-Windows30 if (!RegisterClassEx(&wcx))

    31 return 0;3233 // Create the window34 hwndMain = CreateWindowEx(0, //Extended window style35 "Lesson2", // Window class name36 "Lesson 2 - A simple win32 application", // Window title37 WS_OVERLAPPEDWINDOW, // Window style38 CW_USEDEFAULT,CW_USEDEFAULT, // (x,y) pos of the window39 CW_USEDEFAULT,CW_USEDEFAULT, // Width and height of the window40 HWND_DESKTOP, // HWND of the parent window (can be null also)41 NULL, // Handle to menu42 hInstance, // Handle to application instance43 NULL); // Pointer to window creation data4445 // Check if window creation was successful46 if (!hwndMain)47 return 0;

    4849 // Make the window visible50 ShowWindow(hwndMain,SW_SHOW);5152 // Process messages coming to this window53 while (GetMessage(&msg,NULL,0,0))54 {55 TranslateMessage(&msg);56 DispatchMessage(&msg);57 }5859 // return value to the system60 return msg.wParam;61 }6263 LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)64 {

    65 switch (msg)66 {67 case WM_DESTROY:68 // User closed the window69 PostQuitMessage(0);70 break;71 default:72 // Call the default window handler73 return DefWindowProc(hwnd,msg,wParam,lParam);74 }75 return 0;76 }

  • 7/25/2019 C Windows Programming Tutorial

    6/22

    6 - 22

    Whew. That was long! Press F9 to compile and run. You have a basic window on your

    screen!

    Breaking i t up

    Messages and the MSG Structure

    The MSG structure is what stores the messages received by your application. Beforegoing any further, letstake a look at the event-driven programming model.

    Event driven programming model

    To understand event driven programming, we draw analogies from the real world.

    1. Apersonplaces an order at a restaurant.

    2. The waiterconveys this order to the chef.

    3.

    The chefgets busy and soon the order is served.

    1. The userclicks the maximize button.2. Windowstells your applicationthat the maximize button has been pressed.

    3. Your applicationthen redraws its window so that it covers the screen.

    Every time windows has to communicate with your application, it sends messages to your

    application. Once all initializations have been done and the window shown on screen, all

    your application has to do is poll for windows messages.

    The lines up to 51 create and show the window and the lines 52-57 poll for messages.

    The GetMessage()function gets the next message to be processed from the message

    queue. GetMessage()returns a non-zero value for every message other than WM_QUIT.This means that the while loop continues until it is time to quit.

    TranslateMessage()translates virtual key messages to character messages.

    DispatchMessage()dispatches the message to a window procedure. This means that for

    messages coming to our window, the MainWndProc()is called by Windows(tm) through

    DispatchMessage().

    How does Windows(tm) know which function to call? Well, we tell Windows(tm) duringWNDCLASSEX initialization [line 18].

    WNDCLASSEX structure

    Every window that you create has an associated WNDCLASSEX structure. The

    WNDCLASSEX structure provides all the information necessary for Windows(tm) to do

  • 7/25/2019 C Windows Programming Tutorial

    7/22

    7 - 22

    perform window related functions like drawing its icon, cursor, menu, calling the

    callback function which will receive messages and so on.

    The WNDCLASSEX structure is defined as,

    typedef struct _WNDCLASSEX {UINT cbSize;UINT style;WNDPROC lpfnWndProc;int cbClsExtra;int cbWndExtra;HANDLE hInstance;HICON hIcon;HCURSOR hCursor;HBRUSH hbrBackground;LPCTSTR lpszMenuName;LPCTSTR lpszClassName;HICON hIconSm;

    } WNDCLASSEX;

    cbSize

    This must always be set to sizeof(WNDCLASSEX).style

    This specifies the class styles. Take a look at your SDK documentation for the

    values this member can take.lpfnWndProc

    Pointer to the WndProc which will handle this windows' messages.

    cbClsExtraNumber of extra bytes to allocate at the end of the WNDCLASSEX structure.

    cbWndExtra

    Number of extra bytes to allocate at the end of the window instance.hInstance

    Identifies the instance that the window procedure of this class is within.

    hIcon

    Handle to the icon associated with windows of this class.

    hCursorHandle to the cursor for windows of this class.

    hbrBackground

    Identifies the class background brush.lpszMenuName

    Identifies the menu for windows of this class.

    lpszClassNamePointer to a NULL terminated string or an atom specifying the class of thisstructure.

    hIconSm

    Handle to the small icon associated with this class.

  • 7/25/2019 C Windows Programming Tutorial

    8/22

    8 - 22

    Registering your window class

    After you've created your window class, you need to tell Windows(tm) about it. This is

    done by registering the class with windows. The function call is RegisterClassEx(..).Once this is done, you can create instances of this window by calling

    CreateWindowEx(..)with the proper arguments.

    Creating the window

    A window is created by calling the CreateWindowEx(..)defined as,

    HWND CreateWindowEx(DWORD dwExStyle, // extended window styleLPCTSTR lpClassName, // pointer to registered class nameLPCTSTR lpWindowName, // pointer to window nameDWORD dwStyle, // window styleint x, // horizontal position of windowint y, // vertical position of window

    int nWidth, // window widthint nHeight, // window heightHWND hWndParent, // handle to parent or owner windowHMENU hMenu, // handle to menu, or child-window identifierHINSTANCE hInstance, // handle to application instanceLPVOID lpParam // pointer to window-creation data);

    Lines 34-43 create the window. If the creation was successful a non-zero handle is

    returned by CreateWindowExafter which ShowWindow()shows the window on thescreen.

    TIP:It is a good idea to keep referring to these functions in your sdk docs while reading

    this tutorial.

  • 7/25/2019 C Windows Programming Tutorial

    9/22

    9 - 22

    Callback functions

    A callback function is the one that receives the messages sent to your application. This is

    where you do something about the message. We provide a pointer to this function while

    defining the window class [line 18].

    Callback functions have to be defined as,

    LRESULT CALLBACKfunction-name(

    HWND hwnd, // Handle of window which received thismessage

    UINT msg, // The messageWPARAM wParam, // Extra informationLPARAM lParam // Extra information);

    HWND hwndThe handle of the window is specified so that you know which window to act

    upon. This is necessary because you may have created more than one instance of

    the window.UINT msg

    This contains the message sent.

    WPARAM wParam and WPARAM lParam

  • 7/25/2019 C Windows Programming Tutorial

    10/22

    10 - 22

    wParam and lParam are used to pass extra info about the message. For example a

    WM_LBUTTONDOWN (left mouse button down) message will have the x and y

    co-ordinates as the upper and lower word of lParam and wParam will tell if anymodifier keys (ctrl, alt, shift) have been pressed.

    MainWndProc

    63 LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAMlParam)64 {65 switch (msg)66 {

    ...

    The switch statement lets us select which message was sent. There are over 200 messages

    that windows can send your application. To read about them, just search for WM_ in

    your sdk docs.

    WM_DESTROY

    ...67 case WM_DESTROY:68 // User closed the window69 PostQuitMessage(0);70 break;

  • 7/25/2019 C Windows Programming Tutorial

    11/22

    11 - 22

    ...

    The WM_DESTROY message is sent to your application when the user teminates the

    application either by clicking the X at the upper right corner, pressing Alt+F4, or quitsthe application by other means.

    PostQuitMessage()causes GetMessage(..)[line 53] to return false and thus breaking

    out of the while loop and exiting the application. The argument to PostQuitMessageisthe return value to the system.

    DefWindowProc(..)

    What about the other 200 or so messages? Surely you, the programmer, aren't going towrite code for all the 200 messages. Fortunately, Windows(tm) provides the

    DefWindowProc(..)function which handles all the messages. For the purposes ofdisplaying a simple window, your MainWndProc could very well have consisted of

    LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAMlParam){

    return DefWindowProc(hwnd,msg,wParam,lParam);}

    What this means is that every time you want to do something about a message, add the

    case switch for the message and write the code which does something about it. All

    messages that you don't want to handle should be passed to the DefWindowProc(). Thisis what we have done in our code.

    ...71 default:72 // Call the default window handler73 return DefWindowProc(hwnd,msg,wParam,lParam);

    ...

    Add ing Funct ional ity

    Lets pop up a MessageBox which will display the co-ordinates of the point where the left

    mouse button was pressed. To do this you will have to handle the

    WM_LBUTTONDOWN message.

    Add this code at line 70

    ...68 PostQuitMessage(0);69 break;70 case WM_LBUTTONDOWN:71 pt.x = LOWORD(lParam);72 pt.y = HIWORD(lParam);73 wsprintf(str,

  • 7/25/2019 C Windows Programming Tutorial

    12/22

    12 - 22

    "Co-ordinates are\nX=%i and Y=%i",pt.x,pt.y);74 MessageBox(hwnd, str, "Left Button Clicked", MB_OK);75 break;76 default:

    ...

    Press F9. This is what you should see when you click anywhere inside the window.

    Exercise

    Try this exercise. Pop up a message every time a key is pressed on the keyboard.

    Hint: Handle the WM_CHAR message. Remember to refer to your sdk docs.

    If you can manage that, give yourself a pat on the back. You now understand the basicsof event-driven programming - the mechanism which Windows(tm) uses to communicatewith your application. You have crossed one of the more difficult hurdles in learning

    windows programming.

    Don't worry if you could not do the exercise or if things are still a bit hazy. These

    concepts will be used in every single lesson after this and it will soon become second

    nature to you.

  • 7/25/2019 C Windows Programming Tutorial

    13/22

    13 - 22

    Understanding GDI Elements - A Part of

    the series on Win32 Programming

    Clickhereto download the source code for this tutorial.

    GDI (which stands for graphics device interface) is what enables you to draw on the

    screen without worrying about the underlying hardware. GDI functions also allow you todraw on other output devices like the printer, memory devices and metafiles. Windows

    provides functions that let you draw - among other stuff - lines, circles, text and images in

    various colors and styles.

    You can think of GDI as a drawing kit complete with paintbrushes, watercolors, canvas,

    rulers and other instruments.

    Device Contexts

    The first thing you must understand is device contexts. A device context is a structurethat defines a set of graphic objects and their associated attributes, as well as the graphicmodes that affect output. The graphic objects include a pen for line drawing, a brush for

    painting and filling, a bitmap for copying or scrolling parts of the screen, a palette for

    defining the set of available colors, a region for clipping and other operations, and a pathfor painting and drawing operations.

    Following our analogy, a device context can be considered as a canvas with certainspecial properties. You can draw and paint on this canvas and it will always appear to

    others the way it was intended, even if the canvas were transformed into a sketch paper ora post-it note.

    Before your application draws anything on screen, it must get its device context. This is

    done through the GetDC()call which is defined as HDC GetDC(HWND hwnd). After you

    are done with drawing, you must release it. This is done by the ReleaseDC()call defined

    as int ReleaseDC(HWND hwnd, HDC hdc).

    Graphics Objects

    Pens and Brushes

    Pens and Brushes are used to draw lines and paint interiors of closed objects.

    Fonts

    TODO

    http://www.geocities.com/Heartland/Meadows/9818/win32tut/gdi.ziphttp://www.geocities.com/Heartland/Meadows/9818/win32tut/gdi.ziphttp://www.geocities.com/Heartland/Meadows/9818/win32tut/gdi.ziphttp://www.geocities.com/Heartland/Meadows/9818/win32tut/gdi.zip
  • 7/25/2019 C Windows Programming Tutorial

    14/22

    14 - 22

    Palettes

    TODO

    Bitmaps

    TODO

    Working Examp le

    Now that all the theory is out of our way, let us put our new knowledge to practice. Inthis chapter we will build an application that lets us draw lines, rectangles, circles and

    bitmaps.

    We will begin with our skeleton code that draws a simple window.

    // draw.c// Pravin Paratey

    #include

    // VariablesHWND hwndMain; // Main window HWND

    // FunctionsLRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAMlParam);

    int WINAPIWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,

    int nCmdShow){

    MSG msg;WNDCLASSEX wcx;

    // Fill in the WNDCLASS Structwcx.cbSize = sizeof(WNDCLASSEX);wcx.style = CS_DBLCLKS;wcx.lpfnWndProc = MainWndProc;wcx.cbClsExtra = 0;wcx.cbWndExtra = 0;

    wcx.hInstance = hInstance;wcx.hIcon = LoadIcon (NULL, IDI_APPLICATION);wcx.hCursor = LoadCursor (NULL, IDC_ARROW);wcx.hbrBackground = (HBRUSH) COLOR_BACKGROUND;wcx.lpszMenuName = NULL;wcx.lpszClassName = "Draw";wcx.hIconSm = NULL;

    // Register classif(!RegisterClassEx(&wcx))

  • 7/25/2019 C Windows Programming Tutorial

    15/22

    15 - 22

    return 0;

    hwndMain = CreateWindowEx(0,"Draw","Draw Example Application",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,400,300,NULL,NULL,hInstance,NULL);

    ShowWindow(hwndMain,nCmdShow);

    while(GetMessage(&msg,NULL,0,0)){

    TranslateMessage(&msg);

    DispatchMessage(&msg);}return msg.wParam;

    }

    // Callback function for the Main Window classLRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAMlParam){

    switch(msg){case WM_DESTROY:

    PostQuitMessage(0);break;

    default:return DefWindowProc(hwnd,msg,wParam,lParam);

    }return 0;

    }

    Selecting the Drawing Shape

    A real application would use a toolbar to let the user select the shape to draw. Since

    creating a toolbar is too much trouble, well address this by using character input from

    the keyboard to switch between the drawing shapes.

    Lets keep a global variable drawShape to indicate the current tool. Add the following

    lines at the beginning of the file. The lines to be added are shown in bold.

    #include

    // Defines#define SHAPE_NULL 0

  • 7/25/2019 C Windows Programming Tutorial

    16/22

    16 - 22

    #define SHAPE_LINE 1#define SHAPE_RECT 2#define SHAPE_CIRCLE 3#define SHAPE_TEXT 4

    // VariablesHWND hwndMain; // Main window HWNDint drawShape; // The shape to draw

    // FunctionsLRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAMlParam);

    Now add the following code to the MainWndProc message handler. This will select the

    current tool.

    LRESULT CALLBACK

    MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){CHAR ch;

    switch(msg){case WM_CHAR:

    if(!drawing){

    ch = (TCHAR) wParam;switch(ch){case 'n': // NULL

    drawShape = SHAPE_NULL;

    break;case 'l': // LINE

    drawShape = SHAPE_LINE;break;

    case 'r': // RECTANGLEdrawShape = SHAPE_RECT;break;

    case 'c': // CIRCLEdrawShape = SHAPE_CIRCLE;break;

    case 'f': // FREEHANDdrawShape = SHAPE_FREEHAND;break;

    }}break;

    case WM_DESTROY:PostQuitMessage(0);

    Drawing Shapes

  • 7/25/2019 C Windows Programming Tutorial

    17/22

    17 - 22

    To draw a shape we will have to

    1. Get the point where the user clicked the left mouse button.2. Draw a ghost shape while the user moves the mouse with the left button down.

    3. Draw the final shape when the user releases the left mouse button.

    This means handling the WM_LBUTTONDOWN, WM_MOUSEMOVE and

    WM_LBUTTONUP messages.

    WM_LBUTTONDOWN

    1. Set drawing flag to indicate drawing has begun.

    2. Store the start point in beginPoint variable.

    3. Text is to be drawn at the current mouse location. If the selected shape is text,draw it.

    WM_MOUSEMOVE

    1. Check if the left mouse button is down and that we are actually drawing (This isnecessary because clicking the mouse outside the window and moving the mouse

    in will also generate this message).

    2. Erase old shape.3. Draw new shape.

    Erasing and drawing this ghost or rubber shape is achieved by setting the draw modeofthe pen to NOTXOR. NOTXOR has the property that drawing twice undoes the effect of

    the first draw.

    WM_LBUTTONUP

    If the drawing flag was set,

    1. Set drawing flag to false

    2. Erase the ghost shape

    3. Draw a permanent one

    LRESULT CALLBACKMainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){

    CHAR ch; // This will contain keyboard inputHDC hdc; // Handle to the device contextHBRUSH hbrush; // Handle to BRUSH objectHBRUSH hOldBrush; // Stores the old BRUSH objectHPEN hPen;static POINT oldPoint; // Stores the old pointstatic POINT beginPoint; // Stores the begin pointPOINT thisPoint; // Stores the current pointstatic bool drawing = false;int ropOld; // Stores the old Raster OperatorRECT rc;

  • 7/25/2019 C Windows Programming Tutorial

    18/22

    18 - 22

    case WM_DESTROY:PostQuitMessage(0);break;

    case WM_LBUTTONDOWN:// Says, We've begun drawingdrawing = true;

    // Store the begin pointbeginPoint.x = LOWORD(lParam); // Returns x co-ordinatebeginPoint.y = HIWORD(lParam); // Returns y co-ordinate// Store the old pointoldPoint = beginPoint;break;

    case WM_LBUTTONUP:if (drawing){

    drawing = false;// Get Device contexthdc = GetDC(hwnd);// Set ROPropOld = SetROP2(hdc, R2_NOTXORPEN);// Get this pointthisPoint.x = LOWORD(lParam);thisPoint.y = HIWORD(lParam);

    switch(drawShape){// This statement isn't neededcase SHAPE_NULL: // Do Nothing

    break;case SHAPE_LINE:

    // Erase old lineMoveToEx(hdc, beginPoint.x, beginPoint.y, NULL);LineTo(hdc, oldPoint.x, oldPoint.y);// Reset ROPSetROP2(hdc, ropOld);// Draw permanent oneMoveToEx(hdc, beginPoint.x, beginPoint.y, NULL);LineTo(hdc, thisPoint.x, thisPoint.y);break;

    case SHAPE_RECT:// Erase old rect

    Rectangle(hdc, beginPoint.x, beginPoint.y,oldPoint.x, oldPoint.y);

    // Reset ROPSetROP2(hdc, ropOld);// Draw permanent oneRectangle(hdc, beginPoint.x, beginPoint.y,

    thisPoint.x, thisPoint.y);break;

    case SHAPE_CIRCLE:// Erase old circleEllipse(hdc, beginPoint.x, beginPoint.y, oldPoint.x,

    oldPoint.y);// Reset ROPSetROP2(hdc, ropOld);// Draw permanent oneEllipse(hdc, beginPoint.x, beginPoint.y, thisPoint.x,

    thisPoint.y);

    break;}ReleaseDC(hwnd, hdc);

    }break;

    case WM_MOUSEMOVE:// Have we begun drawing?// Is the left button down?if (drawing && ((MK_LBUTTON & wParam) == MK_LBUTTON)){

    // Get Device contexthdc = GetDC(hwnd);

  • 7/25/2019 C Windows Programming Tutorial

    19/22

    19 - 22

    // Set rop to NOTXOR so that we can draw and eraseropOld = SetROP2(hdc, R2_NOTXORPEN);// Store this pointthisPoint.x = LOWORD(lParam);thisPoint.y = HIWORD(lParam);

    switch(drawShape){

    // This statement isn't neededcase SHAPE_NULL: // Do Nothingbreak;

    case SHAPE_LINE:// Erase old lineMoveToEx(hdc, beginPoint.x, beginPoint.y, NULL);LineTo(hdc, oldPoint.x, oldPoint.y);// Draw new oneMoveToEx(hdc, beginPoint.x, beginPoint.y, NULL);LineTo(hdc, thisPoint.x, thisPoint.y);break;

    case SHAPE_RECT:// Erase old rectRectangle(hdc, beginPoint.x, beginPoint.y,

    oldPoint.x, oldPoint.y);// Draw new oneRectangle(hdc, beginPoint.x, beginPoint.y,

    thisPoint.x, thisPoint.y);break;case SHAPE_CIRCLE:

    // Erase old circleEllipse(hdc, beginPoint.x, beginPoint.y, oldPoint.x,

    oldPoint.y);// Draw new oneEllipse(hdc, beginPoint.x, beginPoint.y, thisPoint.x,

    thisPoint.y);break;

    }oldPoint = thisPoint;SetROP2(hdc, ropOld);ReleaseDC(hwnd, hdc);

    }break;

    default:return DefWindowProc(hwnd,msg,wParam,lParam);

    Drawing Lines

    The LineTo function draws a line from the current position to the point specified in itsarguments. Before drawing a line, we must move our pen to the starting co-ordinates.

    This is done through the MoveToEx function.

    Raster Operations

    Raster Operations specify how the current PEN and BRUSH colors will be combined

    with the colors on the screen.

    R2_NOTXORPEN

    R2_NOTXOR is really NOT (XOR (current_color, screen_color)). For two one bitnumbers, the truth table is,

  • 7/25/2019 C Windows Programming Tutorial

    20/22

    20 - 22

    X Y XOR(X,Y) NOT(XOR(X,Y))0 0 0 10 1 1 01 0 1 01 1 0 1

    This is a good time to compile and run your app. Try switching tools and drawing a fewlines, rectangles and ellipses. Your screen should look something like this,

    Whats with the white interior?

    The inside of the rectangle and circle is filled in white because it is the default brush. Ifyou dont want the insides to be filled, add the following code.

    ...ReleaseCapture();

    // Get Device contexthdc = GetDC(hwnd);

    // Set brush to hollowlogbrush.lbStyle = BS_HOLLOW;hbrush = CreateBrushIndirect(&logbrush);holdbrush = (HBRUSH)SelectObject(hdc, hbrush);

    // Set ROPropOld = SetROP2(hdc, R2_NOTXORPEN);// Get this pointthisPoint.x = LOWORD(lParam);...

    SelectObject(hdc, holdbrush); // Restore the brushDeleteObject(hbrush); // Free memoryReleaseDC(hwnd, hdc);

    ...

  • 7/25/2019 C Windows Programming Tutorial

    21/22

    21 - 22

    To change the fill color, add the code:

    ...ReleaseCapture();// Get Device contexthdc = GetDC(hwnd)

    hbrush = CreateSolidBrush(RGB(255,0,0)); //RED brushholdbrush = (HBRUSH)SelectObject(hdc, hbrush);

    // Set ROPropOld = SetROP2(hdc, R2_NOTXORPEN);// Get this pointthisPoint.x = LOWORD(lParam);...SelectObject(hdc, holdbrush); // Restore the brushDeleteObject(hbrush); // Free memoryReleaseDC(hwnd, hdc);

    ...

    Drawing Text

    Windows provides a variety of functions to draw text. We will use the DrawTextEx()function defined as

    int DrawTextEx(HDC hdc, // handle to device contextLPTSTR lpchText, // pointer to string to drawint cchText, // length of string to drawLPRECT lprc, // pointer to rectangle coordinatesUINT dwDTFormat, // formatting optionsLPDRAWTEXTPARAMS lpDTParams // pointer to structure for options);

    Add this code to draw text:

    WM_CHAR

    ...case 'c': // CIRCLE

    drawShape = SHAPE_CIRCLE;break;

    case 't': // TEXTdrawShape = SHAPE_TEXT;

    break;...

    WM_MOUSEMOVE

    ...case SHAPE_CIRCLE:

    // Erase old circle

  • 7/25/2019 C Windows Programming Tutorial

    22/22

    Ellipse(hdc, beginPoint.x, beginPoint.y, oldPoint.x,oldPoint.y);

    // Draw new oneEllipse(hdc, beginPoint.x, beginPoint.y, thisPoint.x,

    thisPoint.y);break;

    case SHAPE_TEXT:// Erase old text rectRectangle(hdc, beginPoint.x, beginPoint.y, oldPoint.x,

    oldPoint.y);// Draw new oneRectangle(hdc, beginPoint.x, beginPoint.y, thisPoint.x,

    thisPoint.y);break;

    ...

    WM_LBUTTONUP

    case SHAPE_TEXT:Rectangle(hdc, beginPoint.x, beginPoint.y, oldPoint.x,

    oldPoint.y);// Reset ROPSetROP2(hdc, ropOld);rc.left = beginPoint.x;rc.top = beginPoint.y;rc.right = thisPoint.x;rc.bottom = thisPoint.y;DrawTextEx(hdc, strOut, lstrlen(strOut), &rc,

    DT_END_ELLIPSIS|DT_NOCLIP|DT_WORDBREAK, NULL);break;

    Persistent Drawing

    If you minimize the window and restore it, youll notice that everything youve drawn is

    erased. This is because Windows sends the WM_PAINTmessage to your application tellingit to redraw its client area. To keep persistent drawings, youve got two options to keep

    a list of all objects and draw them on every call to WM_PAINTor to keep a snapshot of the

    image and redraw it on WM_PAINT.


Recommended