// Simple Win32 application to demonstrate drawing to a window // Chris Lomont Feb 2000, Visual C++ 6.0 // all windows programs include this to access the windows API #include #include // for some more standard C functions we want // this function will do the drawing. It is passed a handle to a window // so it knows which window to draw on. void PaintScreen(HWND hwnd) { PAINTSTRUCT ps; HDC hdc; // we begin the painting by acquiring some resources we'll need BeginPaint(hwnd,&ps); hdc = GetDC(hwnd); // get the size of the region we have to draw on... // size of window, 0,0 is upper left corner, rest positive directions int win_dx, win_dy; RECT rect; // Note: this is the size of the drawble part of the window // not the 640 by 480 size we requested (the total window size) GetClientRect(hwnd,&rect); win_dx = rect.right - rect.left; win_dy = rect.bottom - rect.top; // we've computed the size of the "canvas" // we'll draw stuff following...... // start with a diagonal line, defaults to black on a white background MoveToEx(hdc,0,0,NULL); // this sets the drawing cursor LineTo(hdc,win_dx,win_dy); // this draws // we can draw a few lines connected with this method // to get a parallelogram MoveToEx(hdc,150,10,NULL); LineTo(hdc,200,10); LineTo(hdc,220,30); LineTo(hdc,170,30); LineTo(hdc,150,10); // this could also be drawn with PolyLine... // draw text "0,0", at position 0,0, and it has 3 characters to show TextOut(hdc,0,0,"0,0",3); // we format the max dimensions into text and draw it in the // lower right corner - try resizing the program with the mouse // to see what happens char text[100]; sprintf(text,"%d,%d",win_dx,win_dy); TextOut(hdc,win_dx - 60,win_dy - 20,text,strlen(text)); // A circle and an ellipse. // Note these are filled in with the current brush (default solid white) Ellipse(hdc,20,20,40,40); // the circle in box 20,20 to 40,40 Ellipse(hdc,40,40,50,70); // and an ellipse // every thing is drawn with the default pen (black), so we'll create another pen HPEN hPen, hPenOld; // we create a solid pen, 2 pixels wide, with RGB color 255,128,0 // (each entry is 0-255, so 255,0,0 is pure red, 0,0,0 is black, etc) hPen = CreatePen(PS_SOLID,2,RGB(255,128,0)); // select the new pen into the device context, saving the old pen (important!) hPenOld = (HPEN)SelectObject(hdc,hPen); // draw a rectangle with this color - still fills with solid white brush Rectangle(hdc,70,70,150,100); // some more functions: Arc, ArcTo, Pie, Polygon, RoundRect, PolyLine // when done with the pen we created, we restore the original pen // and destroy the one we created (avoids resource leaks) SelectObject(hdc,hPenOld); DeleteObject(hPen); // we'll draw some cubic bezier curve splines // note we're back to default black pen, 1 pixel wide POINT points[10]; // 10 points we'll use for (int pos = 0; pos < 10; pos++) { points[pos].x = 300 + pos*20; if (pos % 2) // set even position points at 10, odd at 100 points[pos].y = 10; else points[pos].y = 100; } PolyBezier(hdc,points,10); // set a box filled with colored pixels for (int i = 50; i < 150; i++) for (int j = 200; j < 250; j++) SetPixel(hdc,i,j,RGB(5*i,7*j,2*i+3*j)); // finally release the stuff we acquired this time (or we'll have resource leaks!!) ReleaseDC(hwnd,hdc); EndPaint(hwnd,&ps); } // PaintScreen // every window needs a loop to process messages. Here is the one for // the window class we defined for this program LONG PASCAL AppWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) { static int xpos, ypos; switch (msg) { case WM_CLOSE: DestroyWindow(hwnd); return FALSE; case WM_DESTROY: PostQuitMessage(0); break; case WM_LBUTTONDOWN: // when left mouse botton pushed down in client area, // store position so we can draw a line xpos = LOWORD(lParam); ypos = HIWORD(lParam); break; case WM_LBUTTONUP: { // left button up draws a line from where it was // pushed down. Not that the WM_PAINT message will erase // any lines we've drawn. You would need to store all of the lines // and draw them back in the paint message HDC hdc = GetDC(hwnd); // get the window device context MoveToEx(hdc,xpos,ypos,NULL); // move to here LineTo(hdc,LOWORD(lParam),HIWORD(lParam)); // draw line ReleaseDC(hwnd,hdc); // release device context } break; case WM_PAINT: PaintScreen(hwnd); return 0L; } // switch message return DefWindowProc(hwnd,msg,wParam,lParam); } // AppWndProc // this routine creates the window, returning TRUE iff it succeeds BOOL AppInit(HINSTANCE hInst,HINSTANCE hPrev,int sw,LPSTR szCmdLine) { WNDCLASS cls; char titleName[] = "SimpleWin32App - Chris Lomont"; char className[] = "SimpleClass"; // if this program is not currently running, create a // window class for it if (!hPrev) { //*** Register a class for the main application window cls.hCursor = LoadCursor(0,IDC_ARROW); // default cursor cls.hIcon = LoadIcon(NULL,IDI_APPLICATION); cls.lpszMenuName = NULL; // no menu cls.lpszClassName = className; cls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // white background cls.hInstance = hInst; cls.style = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW; cls.lpfnWndProc = (WNDPROC)AppWndProc; // our window function cls.cbClsExtra = 0; cls.cbWndExtra = 0; if (!RegisterClass(&cls)) return FALSE; // return if failed - no point in going on } int x,y,dx,dy; // start positions, sizes dx = 640; // request a 640 by 480 pixel window dy = 480; // get screen sizes, and center this window we're making x = (GetSystemMetrics(SM_CXSCREEN)-dx)/2; y = (GetSystemMetrics(SM_CYSCREEN)-dy)/2; // center it HWND hwndApp = CreateWindow (className, // Class name titleName, // Caption WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | // for resizing WS_MAXIMIZEBOX | WS_MINIMIZEBOX, // Style bits x,y, // upper left corner position dx,dy, // size of the window 0, // Parent window (no parent) 0, // use class menu hInst, // handle to window instance 0 // no params to pass on ); ShowWindow(hwndApp,SW_SHOWNORMAL); // display the window return TRUE; // we succeeded } // AppInit // every windows porgram starts at WinMain. This is the definition int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; //*** Call initialization procedure if (!AppInit(hInstance,hPrevInstance,nCmdShow,lpCmdLine)) return FALSE; //*** Polling messages from event queue until quit for (;;) { if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } // WinMain // end - SimpleWinApp.cpp