Click to See Complete Forum and Search --> : Shifting a DC -
.pcbrainbuster
November 19th, 2007, 01:09 PM
Hello again,
When you create a DC it's x, y, w, and h is the same as your client area. How would I be able to change it to something else? If you have a look at paint for exaple you'll see that the drawing zone is clearly away from the client zone.
Thanks.
LoKi_79
November 19th, 2007, 04:46 PM
Hello again,
When you create a DC it's x, y, w, and h is the same as your client area. How would I be able to change it to something else? If you have a look at paint for exaple you'll see that the drawing zone is clearly away from the client zone.
Thanks.the easiest way is to make a child window specifically for displaying the 'drawing zone'. then you only have to worry about an offset when you create that window (and you will also need to resize it whenever you resize the main window).
then you can put all the mouse input/drawing commands into the child window's wndproc - which is also a nice way to separate those commands from your main windows wndproc.
.pcbrainbuster
November 19th, 2007, 06:02 PM
Now that's clever! But I'm already having problem recieving input with another static control are you sure this is? Or are you talking about another control?
Thanks.
JamesSchumacher
November 19th, 2007, 07:24 PM
Drawing in a child control can be done. That's how paint does it.
Another example is in a game I am writing. (Nowhere near finished).
Download from this (http://cid-f7d26664ce20e649.skydrive.live.com/self.aspx/Public/Demos) folder EZGameLib.dll and RPGXtreme.exe into the same folder...
Go through the menus until you see GameBuilder, then select that. Select 'Image Editor' from the combo box and try it out. You will see, that I am drawing with 'tools' in a child control.
.pcbrainbuster
November 20th, 2007, 04:53 PM
Well I tried to download the stuff but couldn't :(
Anyway, I made a static control and made a Memory DC in it, there is yet another offset issue (when I make a line in one area it comes out about 10 - 50 pixels from where it should be) also how do you position something perfectly in the middle?
Thanks.
JamesSchumacher
November 20th, 2007, 04:57 PM
Point center.
const long nWidth = 640;
const long nHeight = 480;
const long nMiddleX = nWidth / 2;
const long nMiddleY = nHeight / 2;
Rectangle center
const long nWidth = 640;
const long nHeight = 480;
RECT rect = { 0,0,300,200 };
const long nRectWidth = rect.right - rect.left;
const long nRectHeight = rect.bottom - rect.top;
const long posX = (nWidth - nRectWidth) / 2;
const long posY = (nHeight - nRectHeight) / 2;
.pcbrainbuster
November 20th, 2007, 05:02 PM
I find out the problem with the offset issue, the mouse coordinates are relevant to the program while the static control's are relevant to the screen, how do I fix this?
Thanks.
.pcbrainbuster
November 20th, 2007, 05:47 PM
Well I fixed that but the lines I draw still have an offset issue!:( Why?
Thanks.
.pcbrainbuster
November 20th, 2007, 05:50 PM
JamesSchumacher : I just noticed your post but need to know how to center a rectangle in my program :)
Thanks.
.pcbrainbuster
November 21st, 2007, 01:35 PM
I think the problem lies in the way I handled the WM_PAINT message. My drawing zone is on a static control, in BeginPaint am I supposed to give the handle of my static control? Also how would I blit the information onto a Memory DC(I know how to do it normally but don't know how to do it when the drawing zone is based on a child)?
Thanks.
JamesSchumacher
November 21st, 2007, 03:29 PM
I think the problem lies in the way I handled the WM_PAINT message. My drawing zone is on a static control, in BeginPaint am I supposed to give the handle of my static control? Also how would I blit the information onto a Memory DC(I know how to do it normally but don't know how to do it when the drawing zone is based on a child)?
/* Make the class name into a global variable */
char szClassName[ ] = "CodeBlocksWindowsApp";
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)
{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default color as the background of the window */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;
/* The class is registered, let's create the program*/
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"Code::Blocks Template Windows App", /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
544, /* The programs width */
375, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
/* Make the window visible on the screen */
ShowWindow (hwnd, nFunsterStil);
/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}
HWND ChildControl;
/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hPaintDC;
PAINTSTRUCT ps;
const RECT rect = { 0,0,100,100 };
HBRUSH hbrFill;
switch (message) /* handle the messages */
{
case WM_PAINT:
DefWindowProc(hwnd,message,wParam,lParam);
hPaintDC = BeginPaint(ChildControl,&ps);
hbrFill = ::CreateSolidBrush(RGB(255,0,0));
::FillRect(hPaintDC,&rect,hbrFill);
::DeleteObject(hbrFill);
EndPaint(hwnd,&ps);
return 0;
case WM_CREATE:
ChildControl = ::CreateWindowExA(0,"STATIC","",WS_BORDER | WS_CHILD,100,10,100,100,hwnd,0,0,0);
ShowWindow(ChildControl,SW_SHOWNORMAL);
return 0;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
In the WM_PAINT message, I call DefWindowProc to have the window background painted, then I do BeginPaint on the child control. I have a red static control on this window!!!
.pcbrainbuster
November 21st, 2007, 04:25 PM
I tried to do the same but nothing changed :( Also in your WM_CREATE handler you might as well just use the style WS_VISIBLE.
Any ideas?
Thanks.
LoKi_79
November 21st, 2007, 04:27 PM
I was not aware you could do the following!
In the WM_PAINT message, I call DefWindowProc to have the window background painted, then I do BeginPaint on the child control. I have a red static control on this window!!!
the WS_BORDER style gives a 1 pixel offset of the red rectangle from the child client area.
LoKi_79
November 21st, 2007, 04:30 PM
i've lost the plot totally - what exactly do you want the program to do? just be able to draw with a pen on a child window?
.pcbrainbuster
November 21st, 2007, 04:52 PM
Well its not like I'm trying to blow something up :p But the basic idea is, there is a static control in my window the houses the Memory DC and is obviously the area in which that I will be drawing, the problem is that when I draw there is a offset issue and the lines end up coming a bit off. The new thing is that anything that uses a Memory DC to draw on works correctly its the Temporary DC that has the issue. That's why I think I have an issue with the WM_PAINT handler.
Thanks.
LoKi_79
November 21st, 2007, 04:55 PM
Well its not like I'm trying to blow something up :p But the basic idea is, there is a static control in my window the houses the Memory DC and is obviously the area in which that I will be drawing, the problem is that when I draw there is a offset issue and the lines end up coming a bit off. The new thing is that anything that uses a Memory DC to draw on works correctly its the Temporary DC that has the issue. That's why I think I have an issue with the WM_PAINT handler.
Thanks.
where is the temporary DC coming from? and when are you drawing on it, with mouse move, etc..?
LoKi_79
November 21st, 2007, 05:00 PM
i have edited JamesSchumacher's code to make the static control into a 'background' that scales with the window:
#include <windows.h>
/* Make the class name into a global variable */
char szClassName[ ] = "CodeBlocksWindowsApp";
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)
{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default color as the background of the window */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;
/* The class is registered, let's create the program*/
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"Code::Blocks Template Windows App", /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
544, /* The programs width */
375, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
/* Make the window visible on the screen */
ShowWindow (hwnd, nFunsterStil);
/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}
HWND ChildControl = NULL;
/* This function is called by the Windows function DispatchMessage() */
return 0;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
what do you want me to do next :p
Marc G
November 22nd, 2007, 05:14 AM
I just took a look at this thread since you mentioned it in another thread (http://www.codeguru.com/forum/showthread.php?t=438581). In that thread I wrote you a small example that behaves like paint with a grayish background and a white "drawing" part in the upper left corner and you can resize the drawing part however you like.
So, I just fail to see the problem you are facing with this and why you would need anything like "shifting DC"...
.pcbrainbuster
November 22nd, 2007, 11:46 AM
Well the design changed so my application would be more dynamic, which required me to move the MDC to another location in my window. Loki79 I think you made a big mistake asking me what I want you to do next :p But getting back to the main objective I think you mis-understood what I meant; The problem is that when the user is drawing a line he/she expects the line to be temporary while he/she is dragging the mouse and when he/she releases the left mouse button the line should no longer be temporary. The problem is that when anything is drawing to the TEMPORARY DC the lines come out slightly further then it should and goes out of the static control but anything that draws to the Memory DC comes out just fine.
Any ideas? :)
Thanks.
LoKi_79
November 22nd, 2007, 12:28 PM
Well the design changed so my application would be more dynamic, which required me to move the MDC to another location in my window. Loki79 I think you made a big mistake asking me what I want you to do next :p But getting back to the main objective I think you mis-understood what I meant; The problem is that when the user is drawing a line he/she expects the line to be temporary while he/she is dragging the mouse and when he/she releases the left mouse button the line should no longer be temporary. The problem is that when anything is drawing to the TEMPORARY DC the lines come out slightly further then it should and goes out of the static control but anything that draws to the Memory DC comes out just fine.
Any ideas? :)
Thanks.
you can't have got the temporary DC in the same way as you got the other one, or they would be the same? are you using CreateCompatibleDC() ?
how can the user drag a line without releasing the button? if it is just a line, there is no difference between drawing to the permanent DC as you go, or copying the relevant section of the temporary one after you release the mouse.
i might have confused you before using a temporary DC for dragging out a selection rectangle? this is what i've been doing today - it draws a temporary selection box and then draws it permanently in green when the mouse button is released:
case WM_LBUTTONDOWN:
if(m_dragRect == 1)
{
m_Rect.left = m_Rect.right = (int)LOWORD(lParam);
m_Rect.top = m_Rect.bottom = (int)HIWORD(lParam);
DrawRubberBand();
}
return 0;
case WM_MOUSEMOVE:
if (wParam == MK_LBUTTON)
{
if(m_dragRect == 1)
{
DrawRubberBand();
m_Rect.right = (int)LOWORD(lParam);
m_Rect.bottom = (int)HIWORD(lParam);
DrawRubberBand();
}
}
case WM_LBUTTONUP:
if(m_dragRect == 1)
{
m_dragRect = 0;
m_drawRect = 1; //tells WM_PAINT that rectangle should be drawn
//CheckRectDimensions(); //not important
//SetSelectedVolume(); //not important
::UpdateWindow(hwnd);
}
return 0;
Even if you want to move the drawing rectangle around, you don't need static.
See attachment for a new version.
This version has resizing rectangles all around the drawing rectangle allowing to move the drawing rectangle. Also, I implemented very basic free-hand drawing. Just click the left mouse button in the white part and start moving the mouse. clicking mouse again, will start a new object.
Everything works perfectly, even if you move the white part around in the window with the resizing handles.
.pcbrainbuster
November 23rd, 2007, 09:27 AM
Thanks for doing that but you're not drawing on anything other then your window, even I managed this, see if you could do it on a static control.
Thanks.
LoKi_79
November 23rd, 2007, 09:38 AM
Thanks for doing that but you're not drawing on anything other then your window, even I managed this, see if you could do it on a static control.
Thanks.are you saying you want to drag a static control around, or just draw things on it that can be moved?
i have in my head that you are trying to 'capture' a section of an image (drag a box around it), and then move it around as you would in paintshop. you don't need a separate control for that at all - just the bits that make up the selected region, a copy of the original bitmap, and the position of the mouse.
Marc G
November 23rd, 2007, 10:05 AM
pcbrainbuster, please state exactly what you are trying to do.
My solution allows you to write a MS Paint clone without problems. You can draw on the white drawing part and move it around without problems. Isn't that what you want??
Please give exact requirements. Thank you.
.pcbrainbuster
November 23rd, 2007, 10:29 AM
Here they are -
- The DC is based in a static control and not part of the main window(so its the DC that belongs to the child)
- Draw on that DC and none other
Results -
- There is an offset issue with the Temporary DC(TDC)
- I can't seem to capture ALL of the screen
Thanks.
Marc G
November 23rd, 2007, 10:33 AM
It seems to me that that is NOT the requirements but your solution. What exactly should be the end result?
Please tell me why you insist on using this static? What do you think you will gain with a static control that you cannot achieve with the methods in my samples?
.pcbrainbuster
November 23rd, 2007, 10:53 AM
Well a static control is the only way I know of how to perfectly position a DC, I think I know what you mis-understood; let's put it this way how would you change the x and y of a DC? BTW, by results I meant problems :)
Thanks :).
Marc G
November 23rd, 2007, 11:54 AM
C'mon, at least do some effort and please check my examples properly.
In my example you can think of the "white drawing part" as a small DC. IF you would test my app you will see that:
you cannot draw outside the white part! and
you can move the white part around in the complete window.
When you draw something in the white part and then you move the white part around, the drawing is properly offsetted
So, the white part is acting exactly like what you want to achieve!
.pcbrainbuster
November 23rd, 2007, 02:18 PM
Sorry, didn't mean to get you angry :-| But there is in fact a problem; If you draw on the rectangle and go all crazy drawing in it, you can only see the drawing that was caught in the rectangle, BUT when you increase the size of the rectangle you see those lines.
I'm just asking and its optional but could you try the same with a static control? Except that you don't have to work on the dragging thing :)
Thanks.
Marc G
November 24th, 2007, 04:44 AM
No, I refuse to use a static control for this problem. It's simpy the wrong way to solve it, period.
Just look at my code, it's very very simple to extend it to clip coordinates to the white rectangle, so that when you draw outside, it will be clipped. Just give it a try. Another option might be to lock the mouse cursor to the white space so you cannot even move the cursor outside the white rectangle.
.pcbrainbuster
November 24th, 2007, 10:20 AM
Lol :) I refuse to use a rectangle :p
I already had the ClipCursor function working for me too :) Don't ask me why but I have chosen to use static control :(
Can anyone please give me an example of basically what I asked above?
Thanks.
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.