awd@dbase.A-T.COM (Alastair Dallas) (09/06/90)
I'm having all kinds of fun adapting my Macintosh skills to programming
Windows 3.0 (I think there are a lot of us doing that just now). I ran
into a slight problem and I thought I'd see what the net says.
I'm writing an application that wants to drag a line around the screen.
So, when the window gets a WM_LBUTTONDOWN message, I call a routine which
tracks the mouse and repeatedly draws this line in XOR mode. On the Mac,
that would be something like:
PenPat(patXOR);
while (StillDown())
{
MoveTo(...);
LineTo(...);
}
(more or less--much detail eliminated)
Imagine my surprise to find nothing like StillDown() in the Windows API.
Fine, I thought, I'll suffice with something like Button(). But it's not
there, either. I ended up using PeekMessage(...WM_LBUTTONUP, WM_LBUTTONUP...).
First question: is this the preferred StillDown() approach?
Second question. What I'm doing is changing the size of two tiled child
windows. I have a parent window which is split horizontally by the two
child windows. I want the user to drag the line which divides the child
windows and thus change the size of both children simultaneously (since tiling
is a given). My problem is that the event is in reference to the parent
window (mouse movement can occur in either child window). However, getting
the DC for the parent and trying to draw there is apparently drawing
invisibly _behind_ the children.
Which leads me to my third and final question. I'm setting the ROP2 code
to the first XOR mode I came to. Is it possible I'm not getting any
output because my mode is invisible?
Thanks in advance for any help or advice.
/alastair/
brianf@umd5.umd.edu (Brian Farmer) (09/07/90)
In article <697@dbase.A-T.COM> awd@dbase.A-T.COM (Alastair Dallas) writes: > >Imagine my surprise to find nothing like StillDown() in the Windows API. >Fine, I thought, I'll suffice with something like Button(). But it's not >there, either. I ended up using PeekMessage(...WM_LBUTTONUP, WM_LBUTTONUP...). >First question: is this the preferred StillDown() approach? For the most part yes, but you should be peeking on WM_MOUSEFIRST to WM_MOUSELAST. On the WM_MOUSEMOVE message you should be doing your erasing and drawing. The windows receiving the WM_LBUTTONDOWN message should issue a SetCapture call to grab ownership of the mouse when it moves over other windows. >window (mouse movement can occur in either child window). However, getting >the DC for the parent and trying to draw there is apparently drawing >invisibly _behind_ the children. > If you don't include the window style WS_CLIPCHILDREN when you create the parent, drawing on the parent should be appear in the child windows where they over lap. Hope this helps, Brian Farmer brianf@umd5.umd.edu
matts@microsoft.UUCP (Matt SAETTLER) (09/08/90)
In article <697@dbase.A-T.COM> awd@dbase.A-T.COM (Alastair Dallas) writes: >I'm having all kinds of fun adapting my Macintosh skills to programming >Windows 3.0 (I think there are a lot of us doing that just now). I ran >into a slight problem and I thought I'd see what the net says. > >I'm writing an application that wants to drag a line around the screen. >So, when the window gets a WM_LBUTTONDOWN message, I call a routine which >tracks the mouse and repeatedly draws this line in XOR mode. On the Mac, >that would be something like: > > PenPat(patXOR); > while (StillDown()) > { > MoveTo(...); > LineTo(...); > } > >(more or less--much detail eliminated) > >Imagine my surprise to find nothing like StillDown() in the Windows API. >Fine, I thought, I'll suffice with something like Button(). But it's not >there, either. I ended up using PeekMessage(...WM_LBUTTONUP, WM_LBUTTONUP...). >First question: is this the preferred StillDown() approach? case WM_LBUTTONDOWN: SetCapture(hwnd); for (;;) // a long time { // just pay attention to MOUSE message. // if you want to get other message, change this. GetMessage(&msg,hwnd,WM_MOUSEFIRST,WM_MOUSELAST); if (msg.message == WM_MOUSEMOVE) { // Do Something... } else if (msg.message == xxx) { // Do Something else... } else if (msg.message == WM_LBUTTONUP) // the important one (don't forget it or else). break; } ReleaseCapture(); break; Of course, if you want to pay attention to lots of messages, you will want a switch. You also will want to put this into a routin if it grows by any more lines. > >Second question. What I'm doing is changing the size of two tiled child >windows. I have a parent window which is split horizontally by the two >child windows. I want the user to drag the line which divides the child >windows and thus change the size of both children simultaneously (since tiling >is a given). My problem is that the event is in reference to the parent >window (mouse movement can occur in either child window). However, getting >the DC for the parent and trying to draw there is apparently drawing >invisibly _behind_ the children. > The parent window probably has the WS_CLIPCHILDREN attribute, so you can't use the parent hwnd to draw over any children. (this is a good thing). You need to get the hwnd of the actual child window (try saving the list of children in the extra info of the parent HWND). You can size your sibling (MoveWindow(hSibling,...); and then UpdateWindow(hSibling);. Here's a neat trick. When you register the class, add some space for a data structure to the class: pClass->lpszClassName = BUTTONCLASS; [...] pClass->lpfnWndProc = ButtonWndProc; pClass->cbWndExtra = sizeof(HANDLE); ----------------------------------- Then, in an include file for the module: typedef struct { int flags; int importantinfo; HANDLE hData; } ButtonWinInfo; #define BUTTONINFO(hwnd) ( (ButtonWinInfo *)(GetWindowWord(hwnd,0))) #define BUTTONHWNDFLAGS(hwnd) (BUTTONINFO(hwnd)->flags) #define BUTTONHWNDINFO(hwnd) (BUTTONINFO(hwnd)->imortantinfo) #define BUTTONHWNDHDATA(hwnd) (BUTTONINFO(hwnd)->hData) ----------------------------------- Then, in ButtonWndProc: case WM_DESTROY: // Free our data structure (and any allocated items in it) GlobalFree(BUTTONHWNDHDATA(hWnd)); LocalFree((HANDLE)BUTTONINFO(hWnd)); break; case WM_CREATE: // Allocate a per-window data structure... h=LocalAlloc(LPTR, sizeof(ButtonWinInfo)); if(!h) return(NULL); // Since we allocated LPTR, the local handle is the local ptr. SetWindowWord(hWnd,0,h); // the macros are lvals and rvals BUTTONHWNDFLAGS(hWnd)= BUTTON_ALLOCATED | BUTTON_NEW; BUTTONHWNDINFO(hWnd) = important stuff; BUTTONHWNDHDATA(hWnd)=GlobalAlloc(GMEM_DISCARDABLE,DATA_SIZE); ... other create stuff break; (note that this code is for example only. I don't usually name things like this and ignore error conditions...) Another neat thing about this is that if you later decide that you want something to be global instead of window-specific, just do this: extern int gBflags; // The global flags for buttons... #define BUTTONHWNDFLAGS(hwnd) (gBflags) Also, if the structure is small, you may just want to add the structure to the WndExtra instead of using local memory: pClass->cbWndExtra = sizeof(ButtonWinInfo); and then change the macros appropriately. Good luck. I transitioned to Windows from the Mac way back in '86 with Windows 1.0.... with just the SDK for documentation.... It actually wasn't that bad. ----------------------------------- Matt Saettler I speak for myself; or so I'm told to say.