Thread: Help. Drawing program

  1. #1
    Registered User
    Join Date
    Nov 2008
    Posts
    44

    Help. Drawing program

    Ims tarting with Windows programming with C++. I did this program with the help of my book, but i still have one problem. While im hlding the mouse Lbutton, if i want to continue draging it to the right or bottom sides out of the window i can, but if i want to do it to the top or left side i cant, my line instantly goes to the opposite side limit. i captured the mouse in the window so i can do this, but i still have that problem. Whats weong with my code?

    Code:
    #include <windows.h>
    #include <string>
    #include <vector>
    using namespace std;
    
    //=========================================================
    // Globals.
    
    HWND ghMainWnd = 0;
    HINSTANCE ghAppInst = 0;
    
    struct Line
    {
    POINT p0;
    POINT p1;
    };
    
    vector<Line> gLines;
    Line gLine;
    
    bool gMouseDown = false;
    
    // Step 1: Define and implement the window procedure.
    
    LRESULT CALLBACK
    WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    
    	// Objects for painting.
    
    	HDC hdc = 0;
    	PAINTSTRUCT ps;
    
    	switch( msg )
    	{
    
    		// Handle left mouse button click message.
    
    	case WM_LBUTTONDOWN:
    
    		// Capture the mouse (we still get mouse input
    		// even after the mouse cursor moves off the client area.
    
    		SetCapture(hWnd);
    		gMouseDown = true;
    
    		// Point that was clicked is stored in the lParam.
    
    		gLine.p0.x = LOWORD(lParam);
    		gLine.p0.y = HIWORD(lParam);
    
    		return 0;
    
    		// Message sent whenever the mouse moves.
    
    	case WM_MOUSEMOVE:
    		if( gMouseDown )
    		{
    			// Current mouse position is stored in the lParam.
    
    			gLine.p1.x = LOWORD(lParam);
    			gLine.p1.y = HIWORD(lParam);
    			InvalidateRect(hWnd, 0, true);
    		}
    		return 0;
    
    	case WM_LBUTTONUP:
    		// Release the captured mouse when the left mouse
    		// button is lifted.
    
    		ReleaseCapture();
    		gMouseDown = false;
    
    		// Current mouse position is stored in the lParam.
    
    		gLine.p1.x = LOWORD(lParam);
    		gLine.p1.y = HIWORD(lParam);
    		gLines.push_back( gLine );
    		InvalidateRect(hWnd, 0, true);
    		return 0;
    
    		// Handle paint message.
    
    	case WM_PAINT:
    		hdc = BeginPaint(hWnd, &ps);
    		if( gMouseDown )
    		{
    			MoveToEx(hdc, gLine.p0.x, gLine.p0.y, 0);
    			LineTo(hdc, gLine.p1.x, gLine.p1.y);
    		}
    		
    		for(int i = 0; i < gLines.size(); ++i)
    		{
    			MoveToEx(hdc, gLines[i].p0.x, gLines[i].p0.y, 0);
    			LineTo(hdc, gLines[i].p1.x, gLines[i].p1.y);
    		}
    		EndPaint(hWnd, &ps);
    
    		return 0;
    
    // Handle key down message.
    
    	case WM_KEYDOWN:
    
    		if( wParam == VK_ESCAPE )
    			DestroyWindow(ghMainWnd);
    
    		return 0;
    
    		// Handle destroy window message.
    
    	case WM_DESTROY:
    		PostQuitMessage(0);
    		return 0;
    	}
    
    	// Forward any other messages we didn't handle to the
    	// default window procedure.
    	
    	return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    
    // WinMain: Entry point for a Windows application.
    
    int WINAPI
    WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR cmdLine, int showCmd)
    {
    
    	// Save handle to application instance.
    
    	ghAppInst = hInstance;
    
    	// Step 2: Fill out a WNDCLASS instance.
    
    	WNDCLASS wc;
    	wc.style = CS_HREDRAW | CS_VREDRAW;
    	wc.lpfnWndProc = WndProc;
    	wc.cbClsExtra = 0;
    	wc.cbWndExtra = 0;
    	wc.hInstance = ghAppInst;
    	wc.hIcon = ::LoadIcon(0, IDI_APPLICATION);
    	wc.hCursor = ::LoadCursor(0, IDC_ARROW);
    	wc.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);
    	wc.lpszMenuName = 0;
    	wc.lpszClassName = "MyWndClassName";
    
    	// Step 3: Register the WNDCLASS instance with Windows.
    
    	RegisterClass( &wc );
    
    	// Step 4: Create the window, and save handle in globla
    	// window handle variable ghMainWnd.
    
    	ghMainWnd = ::CreateWindow("MyWndClassName", "MyWindow",
    		WS_OVERLAPPEDWINDOW, 200, 200, 640, 480, 0, 0,
    		ghAppInst, 0);
    	
    	if(ghMainWnd == 0)
    	{
    		::MessageBox(0, "CreateWindow - Failed", 0, 0);
    		return false;
    	}
    
    	// Step 5: Show and update the window.
    
    	ShowWindow(ghMainWnd, showCmd);
    	UpdateWindow(ghMainWnd);
    
    	// Step 6: Enter the message loop and don't quit until
    	// a WM_QUIT message is received.
    
    	MSG msg;
    	ZeroMemory(&msg, sizeof(MSG));
    
    	while( GetMessage(&msg, 0, 0, 0) )
    	{
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	}
    
    	// Return exit code back to operating system.
    
    	return (int)msg.wParam;
    }

  2. #2
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    Code:
    #include <windows.h>
    #include <string>
    #include <vector>
    using namespace std;
    
    //=========================================================
    // Globals.
    
    HWND ghMainWnd = 0;
    HINSTANCE ghAppInst = 0;
    
    
    POINT p1;
    
    struct Line
    {
        POINT p0;
        POINT p1;
    };
    
    RECT rcClient;
    vector<Line> gLines;
    Line gLine;
    
    bool gMouseDown = false;
    
    // Step 1: Define and implement the window procedure.
    LRESULT CALLBACK
        WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        int i;   
     // Objects for painting.
        HDC hdc = 0;
        PAINTSTRUCT ps;
        switch( msg )
        {
                // Handle left mouse button click message.
            case WM_LBUTTONDOWN:
                // Capture the mouse (we still get mouse input
                // even after the mouse cursor moves off the client area.
                SetCapture(hWnd);
                GetWindowRect(hWnd, &rcClient );
                // Restrict the cursor
                ClipCursor( &rcClient );            
                gMouseDown = true;
                // Point that was clicked is stored in the lParam.
                gLine.p0.x = LOWORD(lParam);
                gLine.p0.y = HIWORD(lParam);
                return 0;
    
                // Message sent whenever the mouse moves.
            case WM_MOUSEMOVE:
                if( gMouseDown )
                {
                    gLine.p1.x = LOWORD(lParam);
                    gLine.p1.y = HIWORD(lParam);
                    if (gLine.p1.x > 32768)
                        gLine.p1.x -= 65536;
                    if (gLine.p1.y > 32768)
                        gLine.p1.y -= 65536; 
                   InvalidateRect(hWnd, 0, true);
                }
                return 0;
    
            case WM_LBUTTONUP:
                // Release the captured mouse when the left mouse
                // button is lifted.
                ReleaseCapture();
                gMouseDown = false;
                // Free the cursor.
                ClipCursor( 0 );            
                gLine.p1.x = LOWORD(lParam);
                gLine.p1.y = HIWORD(lParam);
                if (gLine.p1.x > 32768)
                    gLine.p1.x  -= 65536;
                if (gLine.p1.y > 32768)
                    gLine.p1.y -= 65536;            
               gLines.push_back( gLine );
                InvalidateRect(hWnd, 0, true);
                return 0;
    
                // Handle paint message.
            case WM_PAINT:
                hdc = BeginPaint(hWnd, &ps);
                if( gMouseDown )
                {
                    MoveToEx(hdc, gLine.p0.x, gLine.p0.y, 0);
                    LineTo(hdc, gLine.p1.x, gLine.p1.y);
                }
                for(i = 0; i < gLines.size(); ++i)
                {
                    MoveToEx(hdc, gLines[i].p0.x, gLines[i].p0.y, 0);
                    LineTo(hdc, gLines[i].p1.x, gLines[i].p1.y);
                }
                EndPaint(hWnd, &ps);
                return 0;
    
                // Handle key down message.
            case WM_KEYDOWN:
    
                if( wParam == VK_ESCAPE )
                    DestroyWindow(ghMainWnd);
                return 0;
    
                // Handle destroy window message.
            case WM_DESTROY:
                PostQuitMessage(0);
                return 0;
        }
    
        // Forward any other messages we didn't handle to the
        // default window procedure.
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    
    // WinMain: Entry point for a Windows application.
    
    int WINAPI
    WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR cmdLine, int showCmd)
    {
        // Save handle to application instance.
        ghAppInst = hInstance;
    
        // Step 2: Fill out a WNDCLASS instance.
        WNDCLASS wc;
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = WndProc;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hInstance = ghAppInst;
        wc.hIcon = ::LoadIcon(0, IDI_APPLICATION);
        wc.hCursor = ::LoadCursor(0, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);
        wc.lpszMenuName = 0;
        wc.lpszClassName = "MyWndClassName";
    
        // Step 3: Register the WNDCLASS instance with Windows.
        RegisterClass( &wc );
    
        // Step 4: Create the window, and save handle in globla
        // window handle variable ghMainWnd.
        ghMainWnd = ::CreateWindow("MyWndClassName", "MyWindow",
            WS_OVERLAPPEDWINDOW, 200, 200, 640, 480, 0, 0,
            ghAppInst, 0);
    
        if(ghMainWnd == 0)
        {
            ::MessageBox(0, "CreateWindow - Failed", 0, 0);
            return false;
        }
    
        // Step 5: Show and update the window.
        ShowWindow(ghMainWnd, showCmd);
        UpdateWindow(ghMainWnd);
    
        // Step 6: Enter the message loop and don't quit until
        // a WM_QUIT message is received.
        MSG msg;
        ZeroMemory(&msg, sizeof(MSG));
    
        while( GetMessage(&msg, 0, 0, 0) )
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        // Return exit code back to operating system.
        return (int)msg.wParam;
    }

  3. #3
    Registered User
    Join Date
    Nov 2008
    Posts
    44
    That was what i was looking for . Well i didnt want to restrict the mouse so i deleted that but it works! thank you! and...can you explain me why you used the numbers 32768 and 65536?
    and...how can i draw a cube just with winapi, without directx or opengl?
    Last edited by Cherry65; 12-21-2008 at 01:31 AM.

  4. #4
    Registered User
    Join Date
    Dec 2008
    Posts
    32
    Quote Originally Posted by Cherry65 View Post
    can you explain me why you used the numbers 32768 and 65536?
    Because 32768 is the maximum positive number of a signed short, and 65536 is 1 more than the maximum value of an unsigned short. I'm not sure why a simple cast to signed wouldn't have worked here, but too lazy to examine the code in detail right now. *grin*

  5. #5
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    but if i want to do it to the top or left side i cant, my line instantly goes to the opposite side limit
    can you explain me why you used the numbers 32768 and 65536?
    The upper left corner of your client area is the origin, x= 0 any y= 0. Thus, when your original code was going to the left or above the origin point, x and/or y was going from zero to 65536 and counting down. The if statements just mapped the area outside of the client window to the client window. That is, when the mouse curser moved to the left of origin, x took on a negative value starting at -1 and on which kept your line on the x axis and to the left of origin. With your original code, once you let go of the mouse button, your line would be mapped to the far right because the x value was something along the lines of 65536 which would incorrectly map the line to the far right even though you expected it to map to the far left.

    In a nutshell, I'm changing the value of x any y when they go the left and/or above the origin to a negative number as opposed to a high positive number.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help with my program...
    By Noah in forum C Programming
    Replies: 2
    Last Post: 03-11-2006, 07:49 PM
  2. Why only 32x32? (OpenGL) [Please help]
    By Queatrix in forum Game Programming
    Replies: 2
    Last Post: 01-23-2006, 02:39 PM
  3. my server program auto shut down
    By hanhao in forum Networking/Device Communication
    Replies: 1
    Last Post: 03-13-2004, 10:49 PM
  4. Simple program for drawing
    By kreyes in forum C Programming
    Replies: 1
    Last Post: 02-08-2002, 01:37 AM
  5. My program, anyhelp
    By @licomb in forum C Programming
    Replies: 14
    Last Post: 08-14-2001, 10:04 PM