-
May 14th, 2015, 02:25 PM
#1
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.
-
May 15th, 2015, 09:44 AM
#2
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.
-
May 15th, 2015, 11:31 AM
#3
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.
-
May 15th, 2015, 12:13 PM
#4
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)
-
May 15th, 2015, 12:39 PM
#5
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.
-
May 15th, 2015, 01:02 PM
#6
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)
-
May 15th, 2015, 01:41 PM
#7
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|