CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7
  1. #1
    Join Date
    May 2015
    Posts
    4

    Problem with AllocConsole + GDI

    Hi!

    I'm having some problems to run GDI in a console window created with AllocConsole.

    In this program I'm painting a circle, pixel by pixel. But if I minimize the console window, then restore it, the drawing done was gone!

    When compiling this code in Mingw g++, without using AllocConsole, the problem do not happens: if I minimize the console window, then restore it, the drawing is there.

    When using C++ Builder, and calling AllocConsole, the problem happens.

    Any toughts?

    Source code for C++ Builder:

    Code:
    #pragma hdrstop
    #pragma argsused
    
    #ifdef _WIN32
    #include <tchar.h>
    #else
    typedef char _TCHAR;
    #define _tmain main
    #endif
    
    #include <stdio.h>
    #include <windows.h>
    #include <math.h>
    
    // Set color of painting
    void Xcolor(unsigned int textcolor, unsigned int bgcolor) {
    	HANDLE screen = NULL;
    	screen = GetStdHandle(STD_OUTPUT_HANDLE);
    
    	int color_attribute = bgcolor;
    	color_attribute = _rotl(color_attribute, 4) | textcolor;
    
    	SetConsoleTextAttribute(screen, color_attribute);
    }
    
    // Set pixel at x, y with rgb color
    void Xpixel(unsigned int x, unsigned int y, unsigned int r, unsigned int g, unsigned int b) {
    	HWND myconsole = GetConsoleWindow();
    	HDC mydc = GetDC(myconsole);
    
    	COLORREF COLOR = RGB(r, g, b);
    
    	SetPixel(mydc, x, y, COLOR);
    	Sleep(10);
    
    	ReleaseDC(myconsole, mydc);
    }
    
    // draw a circle at rx, ry with radio and rgb color as specified
    void Xsphere(int rx, int ry, int radio, unsigned int r, unsigned int g,
    	unsigned int b) {
    	const double pi = 3.14159265;
    
    	for (double d = 0; d <= 2 * pi; d += 0.01) {
    		int x = rx + sin(d) * radio;
    		int y = ry + sin(d + (pi / 2)) * radio;
    		Xpixel(x, y, r, g, b);
    	}
    }
    
    int _tmain(int argc, _TCHAR* argv[]) {
    	AllocConsole();
    	Xcolor(2, 4);
    	Xsphere(10, 10, 10, 0, 255, 0);
    	system("pause");
    	return 0;
    }
    Last edited by cfarl; May 15th, 2015 at 12:29 PM.

  2. #2
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Problem with AllocConsole + GDI

    1) console windows don't do graphics.
    if you "paint" on the desktop/system DC, then whatever you paint there will be removed when something else paints over it.

    2) even in a windows app, you typically need to repaint everything you need to show in your WM_PAINT handler. This is part of the way Windows works.

  3. #3
    Join Date
    May 2015
    Posts
    4

    Re: Problem with AllocConsole + GDI

    Hi, OReubens!

    Thanks for your reply. I agree with you, every place I looked for a information says that I have to use a window with GDI, and not use console.

    I see the WM_PAINT problem, specificaly, in console, you cannot get this handler, even if you are using something like that:

    Code:
    HWND hwndConsole = GetConsoleWindow();
     SetWindowLong(hwndConsole, GWL_WNDPROC, (LONG)ConsoleProc);
    Just to know, the old Turbo Pascal and Turbo C does not use the console window to draw?

    I wanted to draw in console window like that, because I'm developing a Pascal compiler, and not I'm developing the 'graph' library to it.

    What really intrigates me is that the 'repainting' problem do not happens when using a console application with Mingw, WITHOUT AllocConsole. You can check this by compiling the following code:

    Code:
    #include <stdio.h>
    #include <windows.h>
    #include <math.h>
    
    // Set color of painting
    void Xcolor(unsigned int textcolor, unsigned int bgcolor) {
    	HANDLE screen = NULL;
    	screen = GetStdHandle(STD_OUTPUT_HANDLE);
    
    	int color_attribute = bgcolor;
    	color_attribute = _rotl(color_attribute, 4) | textcolor;
    
    	SetConsoleTextAttribute(screen, color_attribute);
    }
    
    // Set pixel at x, y with rgb color
    void Xpixel(unsigned int x, unsigned int y, unsigned int r, unsigned int g, unsigned int b) {
    	HWND myconsole = GetConsoleWindow();
    	HDC mydc = GetDC(myconsole);
    
    	COLORREF COLOR = RGB(r, g, b);
    
    	SetPixel(mydc, x, y, COLOR);
    	Sleep(10);
    
    	ReleaseDC(myconsole, mydc);
    }
    
    // draw a circle at rx, ry with radio and rgb color as specified
    void Xsphere(int rx, int ry, int radio, unsigned int r, unsigned int g,
    		unsigned int b) {
    	const double pi = 3.14159265;
    
    	for (double d = 0; d <= 2 * pi; d += 0.01) {
    		int x = rx + sin(d) * radio;
    		int y = ry + sin(d + (pi / 2)) * radio;
    		Xpixel(x, y, r, g, b);
    	}
    }
    
    int main() {
    	Xcolor(2, 4);
    	Xsphere(10, 10, 10, 0, 255, 0);
    	system("pause");
    	return 0;
    }
    So, I think there is a configuration in AllocConsole to fix the 'repaint' problem.

    Any thoughts?

    With best regards,

    cfarl
    Last edited by cfarl; May 15th, 2015 at 04:53 PM.

  4. #4
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,825

    Re: Problem with AllocConsole + GDI

    When posting code, please use code tags. Go Advanced, select the formatted code and click '#'

    Just to know, the old Turbo Pascal and Turbo C does not use the console window to draw?
    These compilers used propriety graph functions (eg circle(), drawpoly(), putpixel() etc) with <graphics.h> header. These functions aren't usually included with other compilers . See http://en.wikipedia.org/wiki/Borland_Graphics_Interface

    There are some emulation libraries available. eg
    http://www.cse.dmu.ac.uk/~bb/Teachin...Interface.html
    http://onecore.net/dev-c-graphics.htm
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  5. #5
    Join Date
    May 2015
    Posts
    4

    Re: Problem with AllocConsole + GDI

    Thanks for your reply, 2kaud.

    In fact, I'm using the WinBGIm library.

    It uses a separeted window to draw, and the WM_PAINT to repaint.

    The code I posted above is more simple than using this library, but has the same rule. If you change some lines in WinBGIm it can be used to draw in console.

    To do it, in winthread.cxx, just replace:

    Code:
    hWindow = CreateWindowEx( 0,                    // Extended window styles
                                  _T( "BGILibrary" ),   // What kind of window
                                  pWndData->title.c_str( ),  // Title at top of the window
    			      pWndData->title.size( )
    			      ? (WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_DLGFRAME)
    			      : (WS_POPUP|WS_DLGFRAME),
                                  left, top, width, height,  // left top width height
                                  NULL,                 // HANDLE to the parent window
                                  NULL,                 // HANDLE to the menu
                                  BGI__hInstance,       // HANDLE to this program
                                  NULL );               // Address of window-creation data
        }
    for:

    Code:
    hWindow = GetConsoleWindow();
    So, even in this libray the 'repaint' problem occurs in console when using AllocConsole.

    If you compile in mingw the 'repaint' problem do not happens...

    I really wanted to draw in console, but there is some point in AllocConsole I missing.

  6. #6
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,825

    Re: Problem with AllocConsole + GDI

    I really wanted to draw in console, but there is some point in AllocConsole I missing.
    AllocConsole() will allocate a console for a program that doesn't already have an attached console (such as a gui program). A process can only have one allocated console at once. If a console has already been allocated then AllocConsole() will report a failure. FreeConsole() can be used to detach a process from its current console so that another console can be attached.

    However, the point remains re the 'repaint' issue with using a console for graphics. The WM_PAINT message for the console window doesn't know anything about the graphics that you have placed on the console window so doesn't re-draw them when it redraws the console window. You might be able to sub-class the console window and after processing the normal WM_PAINT function then call your own function to draw the required graphics.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  7. #7
    Join Date
    May 2015
    Posts
    4

    Re: Problem with AllocConsole + GDI

    Subclass would be nice, but subclassing the console window to replace 'wndproc' cannot be done...

    I tried it, but do not worked.

    Code:
    HWND hwndConsole = GetConsoleWindow();
     SetWindowLong(hwndConsole, GWL_WNDPROC, (LONG)ConsoleProc);
     printf("Error: %d",GetLastError());
    
    LRESULT CALLBACK ConsoleProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
        ...
    }
    It states "Error 5" (Access is denied)

    Other people reported the same problem here:

    http://stackoverflow.com/questions/1...le-application

    Just to say, I tried OpenBgi (http://sourceforge.net/projects/open...e=typ_redirect), and it has better results than winbgi.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured