C++ Visual Studios 2003 GUI Help - error C2664: 'TextOutA'

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Challenger
    New Member
    • Apr 2006
    • 11

    C++ Visual Studios 2003 GUI Help - error C2664: 'TextOutA'

    Hi I am creating a program in C++ using visual studios 2003, and for a project I am required to create a application. In this application for testing purposes I am outputing a number to show that a certain key was pressed. I am getting

    error C2664: 'TextOutA' : cannot convert parameter 4 from 'std::string' to 'LPCSTR'

    As the error.

    My code is

    Code:
     /*	Trim fat from windows*/ 
    #define WIN32_LEAN_AND_MEAN	
    #pragma comment(linker, "/subsystem:windows")
    /*	Pre-processor directives*/
    //#include "stdafx.h"
    #include <windows.h>
    #include <iostream>
    #include <String>
    #include <cString>
    using namespace std;
    /*
    #define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
    #define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
    */
     
    /*	Windows Procedure Event Handler*/
    string keyin="0";
    void GamePaint(HDC hDc);
     
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
     
    	PAINTSTRUCT ps;
    	/*	Device Context*/
    	HDC hDC; 
    	/*	Text for display*/
    	/*	Switch message, condition that is met will execute*/
    	string trst;
    	switch(message)
    	{
    		/*	Window is being created*/
    		case WM_CREATE: 
    			return 0;
    			break;
    		/*	Window is closing*/
    		case WM_DESTROY: 
    			PostQuitMessage(0);
    			return 0;
    			break;
     
    		/*	Window needs update*/
    		case WM_KEYDOWN:
    		{
    			// get virtual key code and data bits
    			int virtual_code = (int)wParam;
    			int key_state = (int)lParam;
     
    			// switch on the virtual_key code to be clean
    			switch(virtual_code)
    			{
    			case VK_RIGHT:
    				{
    					keyin="1"; 
    				} break;
    			case VK_LEFT: 
    				{ 
    					keyin="2";
    				} break;
    			case VK_UP: 
    				{
    					keyin="3";
    				} break;
    			case VK_DOWN: 
    				{
    					keyin="4";
    				} break;
     
    			// more cases...
     
    			default: break;
    		} // end switch
     
    		// tell windows that you processed the message
    		return(0);
    		} break;
     
    		case WM_PAINT: 
    			hDC = BeginPaint(hwnd,&ps);
    			GamePaint(hDC);
    			/*	Set txt color to blue*/
    			trst="Hi";
    			SetTextColor(hDC, RGB(0,0,255));
    			TextOut(hDC,150,150,(trst),2);
    //			TextOut(hDC,0,0,keyin,strlen(keyin));
    			EndPaint(hwnd, &ps);
    			return 0;
    			break;
    		default:
    			break;
    	}
    	return (DefWindowProc(hwnd,message,wParam,lParam));
    }
     
     
     
    void GamePaint(HDC hDC)
    {
    	HPEN hBluePen = CreatePen(PS_SOLID, 2, RGB(0,0,255));
    	HBRUSH hPurpleBrush = CreateSolidBrush(RGB(255,0,255));
    	HBRUSH hRedBrush = CreateSolidBrush(RGB(255,0,0));
    	RECT rect={80,80,129,129};
     
    //	HPEN hPen = SelectObject(hDC, hBluePen); 
    //	Image image(L"test.jpg");
    //	graphics.DrawImage(&image, 60, 10);
     
    	MoveToEx(hDC, 10,40,NULL);
    	LineTo(hDC, 44, 10);
    	LineTo(hDC, 78, 40);
    	SelectObject(hDC, hRedBrush);
    	Ellipse(hDC, 150, 150, 180, 180);
     
    	SelectObject(hDC, hBluePen);
     
    	SetTextColor(hDC, RGB(0,0,255));
     
    	Rectangle(hDC, 80, 80, 130, 130);
    	FillRect(hDC, &rect,hPurpleBrush);
    	DeleteObject(hBluePen);
     
     
    }
    /*	Main function*/
    int APIENTRY WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
    {
    	WNDCLASSEX windowClass;		//window class
    	HWND		hwnd;				//window handle
    	MSG			msg;				//message
    	bool		done;				//flag saying when app is complete
    	/*	Fill out the window class structure*/
    	windowClass.cbSize = sizeof(WNDCLASSEX);
    	windowClass.style = CS_HREDRAW | CS_VREDRAW;
    	windowClass.lpfnWndProc = WndProc;
    	windowClass.cbClsExtra = 0;
    	windowClass.cbWndExtra = 0;
    	windowClass.hInstance = hInstance;
    	windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    	windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    	windowClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    	windowClass.lpszMenuName = NULL;
    	windowClass.lpszClassName = "MyClass";
    	windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
    	/*	Register window class*/
    	if (!RegisterClassEx(&windowClass))
    	{
    		return 0;
    	}
    	/*	Class registerd, so now create window*/
    	hwnd = CreateWindowEx(NULL,		//extended style
    		"MyClass",			//class name
    		"A Real Win App",		//app name
    		WS_OVERLAPPEDWINDOW |		//window style
    		WS_VISIBLE |
    		WS_SYSMENU,
    		100,100,			//x/y coords
    		400,400,			//width,height
    		NULL,				//handle to parent
    		NULL,				//handle to menu
    		hInstance,			//application instance
    		NULL);				//no extra parameter's
    	/*	Check if window creation failed*/
    	if (!hwnd)
    		return 0;
    	done = false; //initialize loop condition variable
    	/*	main message loop*/
    	while(!done)
    	{
    		PeekMessage(&msg,hwnd,NULL,NULL,PM_REMOVE);
    		if (msg.message == WM_QUIT) //check for a quit message
    		{
    			done = true; //if found, quit app
    		}
    		else
    		{
    			/*	Translate and dispatch to event queue*/
    			TranslateMessage(&msg); 
    			DispatchMessage(&msg);
    		}
    	}
    	return msg.wParam;
    }
    any help would be appreciated. Thanks
    Last edited by Niheel; Apr 4 '06, 07:42 AM.
  • Banfa
    Recognized Expert Expert
    • Feb 2006
    • 9067

    #2
    To start with post code between &#91;code&#9 3 and &#91;/code&#93 it will make it easier to read.

    The problem is that you are using components from 2 different libraries, namely the C++ STL and the Windows 32 bit API(WIN32). The Windows 32 bit API has no knowledge of the C++ STL and vis versa.

    In the line

    TextOut(hDC,150 ,150,(trst),2);

    you are trying to pass an STL sting object(trst) to WIN32 function, however the WIN32 function is expecting a variable of type LPCSTR (which boils down to const char * if you care to look through the header files).

    The string std object no longer deals in C style strings and has no default operator that can convert a string STL object to the C style string pointer. However it does have a function to do the same.

    The MFC also has an alternate string class CString which does know about C style strings as it is a helper class made to integrate with the WIN32 API.

    You have 3 options
    1. Keep the stl string, where you need to pass it to the WIN32 API used the c_str member function to convert it to a useable type

      TextOut(hDC,150 ,150,(trst.c_st r()),2);
    2. Use a CString instead, it knows how to convert itself to LPCSTR
      CString trst;
      trst = "Hi";
      TextOut(hDC,150 ,150,trst,2);
    3. Go back to an old fasioned array of characters
      char trst[10];
      strcpy(trst, "Hi");
      TextOut(hDC,150 ,150,trst,2);

    Comment

    • Challenger
      New Member
      • Apr 2006
      • 11

      #3
      Thanks

      Thank you very much that worked. I am also working on something were I am getting the user input using the arrow keys which moves a circle. The only problems that I am having is that it is not redrawing the screen is just redraws another circule every time so I end up with a line of circles. Any suggestions on how to fix this. You help is much aprechated.

      Comment

      • Banfa
        Recognized Expert Expert
        • Feb 2006
        • 9067

        #4
        Again 3 options
        1. Redraw your oiginal circle in the background colour before drawing the new one.
        2. If this constitues editing then you can draw the circle by inverting the colour of the bits (using xor) to get them back just invert them again. Once you have the position you want draw the circle in the requrired colour.
        3. Probably the proper way is to redraw the screen. Having decided where you want the circle and set the data invalidate the area of the screen that is being updated (if you invalidate the whole screen then it will work but it will be a lot slower) and call UpdateWindow. Handle the WM_PAINT message to actually draw your window. This will also ensure that if another window is place over the top of your window and then removed it will be properly redrawn

        Comment

        • Challenger
          New Member
          • Apr 2006
          • 11

          #5
          I am still having problems with my code so far. It seems like no matter what i do I ehter louse input from the keyboard and the graphics are steady, or i have input from the keyboard and the graphics are all messed up. my code so far is.


          Code:
           /*	Trim fat from windows*/ 
          #define WIN32_LEAN_AND_MEAN	
          #pragma comment(linker, "/subsystem:windows")
          /*	Pre-processor directives*/
          //#include "stdafx.h"
          #include <windows.h>
          #include <iostream>
          //#include <Gdiplusheaders.h>
          //#include <gdiplus.h>
           
          #define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
          #define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
           
           
          /*	Windows Procedure Event Handler*/
          int keyin=0;
          int keyin2=0;
          int x=0;
          int y=0;
          int f=0;
          void GamePaint(HDC hDc);
          int keyma();
          LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
          {
           
          	PAINTSTRUCT ps;
          	/*	Device Context*/
          	HDC hDC; 
          //	MSG			msg;
          	RECT rect; // rectangle of window
          	/*	Text for display*/
          	/*	Switch message, condition that is met will execute*/
          	switch(message)
          	{
          		/*	Window is being created*/
          		case WM_CREATE: 
          			return 0;
          			break;
          		/*	Window is closing*/
          		case WM_DESTROY: 
          			PostQuitMessage(0);
          			return 0;
          			break;
          		/*	Window needs update*/
          		case WM_KEYDOWN:
          		{
          			// get virtual key code and data bits
          			int virtual_code = (int)wParam;
          			int key_state = (int)lParam;
           
          			// switch on the virtual_key code to be clean
          			if (KEYDOWN(VK_ESCAPE))
          				SendMessage(hwnd,WM_CLOSE,0,0);
           
          			switch(virtual_code)
          			{
          			case VK_RIGHT:
          				{
          					keyin2=5;
          					keyin=0;
          				} break;
          			case VK_LEFT: 
          				{ 
          					keyin2=-5;
          					keyin=0;
          				} break;
          			case VK_UP: 
          				{
          					keyin=-5;
          					keyin2=0;
          				} break;
          			case VK_DOWN: 
          				{
          					keyin=5;
          					keyin2=0;
          				} break;
          			// more cases...
           
          			default: break;
          		} // end switch
           
          		// tell windows that you processed the message
          		return(0);
          		} break;
          		case WM_PAINT:
          			 {
           
          				// simply validate the window
          				UpdateWindow(hwnd);
          				hDC = GetDC(hwnd);
           
          				// you would do all your painting here
          				GamePaint(hDC);
           
          				ReleaseDC(hwnd,hDC);
           
           
          			/*
          				// get client rectangle of window – use Win32 call
          				GetClientRect(hwnd,&rect);
          				// validate window
          				ValidateRect(hwnd,&rect);
          		*/
          				// return success
          				return(0);
          			} break;
          		default:
          			break;
          	}
          	return (DefWindowProc(hwnd,message,wParam,lParam));
          }
           
           
          void GamePaint(HDC hDC)
          {
          	HPEN hBluePen = CreatePen(PS_SOLID, 2, RGB(0,0,255));
          	HBRUSH hPurpleBrush = CreateSolidBrush(RGB(255,0,255));
          	HBRUSH hRedBrush = CreateSolidBrush(RGB(255,0,0));
          	RECT rect={80,80,129,129};
           
          	x=x+keyin2;
          	y=y+keyin;
          	keyin=0;
          	keyin2=0;
           
           
          	MoveToEx(hDC, 10,40,NULL);
          	LineTo(hDC, 44, 10);
          	LineTo(hDC, 78, 40);
          	SelectObject(hDC, hRedBrush);
          	Ellipse(hDC, x, y, x+10, y+10);
           
          	SelectObject(hDC, hBluePen);
           
          	SetTextColor(hDC, RGB(0,0,255));
          	Rectangle(hDC, 80, 80, 130, 130);
          	FillRect(hDC, &rect,hPurpleBrush);
          	DeleteObject(hBluePen);
           
          	HPEN hBlackPen = CreatePen(PS_SOLID, 1, RGB(0,0,0));
          			HBRUSH hBlackBrush = CreateSolidBrush(RGB(0,0,0));
           
          			SelectObject(hDC, hBlackPen);
          			SelectObject(hDC, hBlackBrush);
          			Rectangle(hDC, 0, 0, 600, 600);
          			FillRect(hDC, &rect, hBlackBrush);
          /*
          			HPEN hBluePen = CreatePen(PS_SOLID, 2, RGB(0,0,255));
          			HBRUSH hPurpleBrush = CreateSolidBrush(RGB(255,0,255));
          			HBRUSH hRedBrush = CreateSolidBrush(RGB(255,0,0));
          			RECT rect={80,80,129,129};
          */
          			//Ellipse(hDC, x, y, x+10, y+10);
           
          			x=x+keyin2;
          			y=y+keyin;
          			keyin=0;
          			keyin2=0;
           
           
          			MoveToEx(hDC, 10,40,NULL);
          			LineTo(hDC, 44, 10);
          			LineTo(hDC, 78, 40);
          			SelectObject(hDC, hRedBrush);
          			Ellipse(hDC, x, y, x+10, y+10);
           
          			SelectObject(hDC, hBluePen);
           
          			SetTextColor(hDC, RGB(0,0,255));
          			Rectangle(hDC, 80, 80, 130, 130);
          			FillRect(hDC, &rect,hPurpleBrush);
          			DeleteObject(hBluePen);
          			DeleteObject(hBlackBrush);
          			DeleteObject(hBlackPen);
           
           
          }
           
          /*	Main function*/
          int APIENTRY WinMain(HINSTANCE hInstance,
          HINSTANCE hPrevInstance,
          LPSTR lpCmdLine,
          int nCmdShow)
          {
          	WNDCLASSEX windowClass;		//window class
          	HWND		hwnd;				//window handle
          	MSG			msg;				//message
          	bool		done;				//flag saying when app is complete
          	/*	Fill out the window class structure*/
          	windowClass.cbSize = sizeof(WNDCLASSEX);
          	windowClass.style = CS_HREDRAW | CS_VREDRAW;
          	windowClass.lpfnWndProc = WndProc;
          	windowClass.cbClsExtra = 0;
          	windowClass.cbWndExtra = 0;
          	windowClass.hInstance = hInstance;
          	windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
          	windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
          	windowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
          	windowClass.lpszMenuName = NULL;
          	windowClass.lpszClassName = "MyClass";
          	windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
          	/*	Register window class*/
          	if (!RegisterClassEx(&windowClass))
          	{
          		return 0;
          	}
          	/*	Class registerd, so now create window*/
          	hwnd = CreateWindowEx(NULL,		//extended style
          		"MyClass",			//class name
          		"Test Program",		//app name
          		WS_OVERLAPPEDWINDOW |		//window style
          		WS_VISIBLE |
          		WS_SYSMENU,
          		100,100,			//x/y coords
          		400,400,			//width,height
          		NULL,				//handle to parent
          		NULL,				//handle to menu
          		hInstance,			//application instance
          		NULL);				//no extra parameter's
          	/*	Check if window creation failed*/
          	if (!hwnd)
          		return 0;
          	done = false; //initialize loop condition variable
           
          	while(!done)
          	{
          		PeekMessage(&msg,hwnd,NULL,NULL,PM_REMOVE);
          		if (msg.message == WM_QUIT) //check for a quit message
          		{
          			done = true; //if found, quit app
          		}
          		else
          		{
          			/*	Translate and dispatch to event queue*/
          			TranslateMessage(&msg); 
          			DispatchMessage(&msg);
          		}
          	}
          	return msg.wParam;
          }
          Your help would be very much apreasheated. And i did try the suggested all ready. (also i did try and add those tags on to make the code easier to read but i can't seem to get them to work.)
          Last edited by Niheel; Apr 5 '06, 06:39 PM.

          Comment

          • Challenger
            New Member
            • Apr 2006
            • 11

            #6
            Urgent

            I with regards to the previous post can any give me an answer since i kind of need it by the end of tonight at the latests before i go to plan B. Any help would be great. Thank you in advance.

            Comment

            • Banfa
              Recognized Expert Expert
              • Feb 2006
              • 9067

              #7
              I do not have a lot of time for this because I am in the middle of a software release but a glance at your code suggests problems in WM_PAINT handler

              Code:
              case WM_PAINT:
              			 {
               
              				// simply validate the window
              				UpdateWindow(hwnd);
              				hDC = GetDC(hwnd);
               
              				// you would do all your painting here
              				GamePaint(hDC);
               
              				ReleaseDC(hwnd,hDC);
               
               
              			/*
              				// get client rectangle of window – use Win32 call
              				GetClientRect(hwnd,&rect);
              				// validate window
              				ValidateRect(hwnd,&rect);
              		*/
              				// return success
              				return(0);
              			} break;
              • Don't call UpdateWindow in WM_PAINT because UpdateWindow sends a WM_PAINT message to the window. Call UpdateWindow from the place that you wish to update the window from (your key handers)
              • Don't use GetDC and ReleaseDC within a WM_PAINT message use BeginPaint and EndPaint
              .

              You dont Invalidate any bits of the screen in the code you have posted which would be required for an update to occur, remember if you are moving an object (like a circle) you need to Invalidate it's starting location and it's ending Location to redraw it properly.

              Comment

              • Challenger
                New Member
                • Apr 2006
                • 11

                #8
                I owuld first of all like to say that i really really apreashate your help with this so far. I don't know if this is a stupid question or not but how do you invalidate the starting location and ending location or is that what updateWindow does. Sorry that I have to bug you again.

                Comment

                • Banfa
                  Recognized Expert Expert
                  • Feb 2006
                  • 9067

                  #9
                  No problem :D

                  UpdateWindow redraws the screen immediately, if you don't call it then Windows will call WM_PAINT in the end but you wont get an immediate update.

                  To invalidate a section of the screen call one of the functions

                  InvalidateRect
                  or
                  InvalidateRgn

                  These respectively invalidate a rectangle on the screen or a region of the screen. InvalidateRect can also be used to invalidate the whole screen but if you needlessly invalidate more of the screen than is required you will slow down the redraw.

                  You can call the invalidate functions more than once before calling UpdateWindow, if you do this the generally windows will redraw the smallest rectangle required to encompass all invalidated areas.

                  So lets assume that you are moving a circle that has a radius of 100 pixels from x=100, y=100 to x=110, y=100 you might do something like the following

                  Code:
                    RECT rect;
                  
                    // Setup start location rectangle
                    rect.top = 100;
                    rect.bottom = 100+(100*2); // y position + 2 times the radius
                    rect.left = 100;
                    rect.right = 100+(100*2); // x position + 2 times the radius
                  
                    // invalidate the start location
                    InvalidateRect( hWnd, &rect, TRUE );
                  
                    // Setup finish location rectangle
                    rect.top = 100;
                    rect.bottom = 100+(100*2); // y position + 2 times the radius
                    rect.left = 110;
                    rect.right = 110+(100*2); // x position + 2 times the radius
                  
                    // Invalidate the finish location
                    InvalidateRect( hWnd, &rect, TRUE );
                  
                    UpdateWindow( hWnd ); // Redraw the invalidated areas
                  NOTE: I have set the invalidated areas to be erased to the background colour (3rd parameter TRUE), however doing this can cause some flicker and if you can avoid it then the redraw will look smoother.

                  What I have sometimes done is to create a bitmap in memory the size of the screen and draw onto the bitmap, the the repaint in WM_PAINT just consists of blting from the bitmap onto the screen without the need to erase to background.

                  Comment

                  • Challenger
                    New Member
                    • Apr 2006
                    • 11

                    #10
                    Thank you so much that part of the program works. The only other thing is that when I close the program the window that I am using closes fine but the program is still running in the process tab of task manager. So pretty much it closes the window but does not terminate the program so any thoughts would be nice. This one is not as critical to other parts. Thanks for your time.

                    Comment

                    • Banfa
                      Recognized Expert Expert
                      • Feb 2006
                      • 9067

                      #11
                      Your message loop is wrong, you should be using GetMessage not PeekMessage. PeekMessage is normally used when you want to create a subsidurary message loop (for instance to keep processing some messages while performing another operation). I used to use PeekMessage a lot back in the days of Windows 2 which was not multi-tasking when I needed to go into a loop but keep the Window working.

                      Your message loop should look something like

                      Code:
                          BOOL bRet;
                      
                          while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
                          { 
                              if (bRet == -1)
                              {
                                  // handle the error and possibly exit
                              }
                              else
                              {
                                  TranslateMessage(&msg); 
                                  DispatchMessage(&msg); 
                              }
                          }

                      Comment

                      • Challenger
                        New Member
                        • Apr 2006
                        • 11

                        #12
                        I just want to take this time to say thank you for the time you took to help me. Because of your help I was able to complete my project in the way that I had wanted with out having to resort to doing a console project at the least minute.

                        Thank you very much.

                        From Challenger
                        Last edited by Challenger; Apr 11 '06, 04:28 AM.

                        Comment

                        • Alphatwo
                          New Member
                          • Aug 2006
                          • 1

                          #13
                          Originally posted by Banfa
                          You have 3 options
                          1. Keep the stl string, where you need to pass it to the WIN32 API used the c_str member function to convert it to a useable type

                            TextOut(hDC,150 ,150,(trst.c_st r()),2);
                          2. Use a CString instead, it knows how to convert itself to LPCSTR
                            CString trst;
                            trst = "Hi";
                            TextOut(hDC,150 ,150,trst,2);
                          3. Go back to an old fasioned array of characters
                            char trst[10];
                            strcpy(trst, "Hi");
                            TextOut(hDC,150 ,150,trst,2);
                          You can use your stl string with TextOut. TextOut requires a LPCSTR parameter, which is defined as "typedef const CHAR * LPCSTR". So, when you see a LPCSTR parameter, the function basicly just want the address of the first character in your string.

                          For a stl string, the address of the first character can easily be obtained:
                          &myString[0];

                          So, to ouput your string, you could use the following:

                          Code:
                          TextOut( hdc, 150, 150, &trst[0], trst.size() );

                          Comment

                          • Banfa
                            Recognized Expert Expert
                            • Feb 2006
                            • 9067

                            #14
                            Originally posted by Alphatwo
                            You can use your stl string with TextOut.
                            I never said you couldn't only that you couldn't use it directly.

                            Originally posted by Alphatwo
                            For a stl string, the address of the first character can easily be obtained:
                            &myString[0];

                            So, to ouput your string, you could use the following:

                            Code:
                            TextOut( hdc, 150, 150, &trst[0], trst.size() );
                            This is an extremely bad idea because you have made 2 assumptions about the internal working of the stl class string

                            1. It uses zero terminators to delimit it strings

                            2. The memory for the string is contiguous

                            Now these may well be true on your system but they are not required by the standard, what is required is the interface and either or both of these assumptions could false for any given system in which case you code will produce undefined behaviour (and most likely a crash).

                            However using trst.c_str() as I suggest will not because this function is defined as returning a standard C zero delimited string.

                            Comment

                            Working...