how to get position of cursor in EDIT control?? - Programmer
This is a discussion on how to get position of cursor in EDIT control?? - Programmer ; How does one get the position of the cursor in an edit control? I am not
talking about the mouse cursor and that is what GetCaretPos() and
GetCursorPos() do. I am talking about the blinking vertical line. There
doesn't seem ...
-
how to get position of cursor in EDIT control??
How does one get the position of the cursor in an edit control? I am not
talking about the mouse cursor and that is what GetCaretPos() and
GetCursorPos() do. I am talking about the blinking vertical line. There
doesn't seem to be any way to get it?? I want to be able to get it in client
or screen coordinates. Thanks!
-
Re: how to get position of cursor in EDIT control??
"Nobody" wrote in message
news:dpbwb.10587$Bk1.14@fed1read05...
> How does one get the position of the cursor in an edit control? I am not
> talking about the mouse cursor and that is what GetCaretPos() and
> GetCursorPos() do. I am talking about the blinking vertical line. There
> doesn't seem to be any way to get it?? I want to be able to get it in
client
> or screen coordinates. Thanks!
I participated in a thread about this a couple of weeks ago...
http://www.google.com/groups?hl=en&l....phx.gbl#link7
....it wasn't you asking this back then was it? In any event, if you have a
repro scenario wherein GetCaretPos is broken, I would love to see it and
have MS look into it. As I said, AFAIK, GetCaretPos is the one and only API
provided for this.
--
Jeff Partch [VC++ MVP]
-
Re: how to get position of cursor in EDIT control??
No it wasn't me... I checked out the thread and like the other poster said,
GetCaretPos and GetCursorPos return the same values. I am running on XP with
comctl6 if that makes a difference.
I did however find a different function a few moments ago that returns the
correct position. GetGUIThreadInfo does the trick.
"Jeff Partch [MVP]" wrote in message
news:eSD9pCisDHA.3224@tk2msftngp13.phx.gbl...
> "Nobody" wrote in message
> news:dpbwb.10587$Bk1.14@fed1read05...
> > How does one get the position of the cursor in an edit control? I am not
> > talking about the mouse cursor and that is what GetCaretPos() and
> > GetCursorPos() do. I am talking about the blinking vertical line. There
> > doesn't seem to be any way to get it?? I want to be able to get it in
> client
> > or screen coordinates. Thanks!
>
> I participated in a thread about this a couple of weeks ago...
>
>
http://www.google.com/groups?hl=en&l....phx.gbl#link7
>
> ...it wasn't you asking this back then was it? In any event, if you have a
> repro scenario wherein GetCaretPos is broken, I would love to see it and
> have MS look into it. As I said, AFAIK, GetCaretPos is the one and only
API
> provided for this.
>
> --
> Jeff Partch [VC++ MVP]
>
>
-
Re: how to get position of cursor in EDIT control??
By the way, I had subclassed an edit control and was calling this when I got
a EM_SHOWBALLOONTIP message.
"Nobody" wrote in message
news:bgcwb.11124$Bk1.3290@fed1read05...
> No it wasn't me... I checked out the thread and like the other poster
said,
> GetCaretPos and GetCursorPos return the same values. I am running on XP
with
> comctl6 if that makes a difference.
>
> I did however find a different function a few moments ago that returns the
> correct position. GetGUIThreadInfo does the trick.
>
> "Jeff Partch [MVP]" wrote in message
> news:eSD9pCisDHA.3224@tk2msftngp13.phx.gbl...
> > "Nobody" wrote in message
> > news:dpbwb.10587$Bk1.14@fed1read05...
> > > How does one get the position of the cursor in an edit control? I am
not
> > > talking about the mouse cursor and that is what GetCaretPos() and
> > > GetCursorPos() do. I am talking about the blinking vertical line.
There
> > > doesn't seem to be any way to get it?? I want to be able to get it in
> > client
> > > or screen coordinates. Thanks!
> >
> > I participated in a thread about this a couple of weeks ago...
> >
> >
>
http://www.google.com/groups?hl=en&l....phx.gbl#link7
> >
> > ...it wasn't you asking this back then was it? In any event, if you have
a
> > repro scenario wherein GetCaretPos is broken, I would love to see it and
> > have MS look into it. As I said, AFAIK, GetCaretPos is the one and only
> API
> > provided for this.
> >
> > --
> > Jeff Partch [VC++ MVP]
> >
> >
>
>
-
Re: how to get position of cursor in EDIT control??
Jeff,
This whole issue is only a part of a bigger problem I was having with a bug
in XP that you might want to point out to MS.
Basically, if you have an edit control with the ES_NUMBER on XP and you type
an invalid character like a letter, etc. XP shows a balloon tooltip telling
you only numbers are acceptable through the EM_SHOWBALLOONTIP message. I
think its a nifty little thing.
Anyways, there is a huge bug in there somewhere that causes whole dialogs
and windows to redraw like mad.
For example, stick an edit control on a property sheet, give it the
ES_NUMBER style, then hold down the 'A' key and the entire property sheet
will flicker like crazy.
My original question was in an attempt to fix this bug. I ended up fixing it
in a completely different way that is pretty dirty, but gets the job done.
After some ugly detective work, it seems there are many bugs involved here:
1) the edit control or the tooltip is calling InvalidateRect with erase =
TRUE on the parent or grandparent of the edit control (the property sheet in
my example). I have proven a single InvalidateRect is getting called by
hooking that function.
2) the balloon tooltip is getting destroyed and recreated when it is still
visible on the screen (more flicker). Ie when you hold down the 'A' key as
in my example, the control keeps getting destroyed and recreated instead of
getting left on the screen.
3) The themed property sheet and/or dialogs dont handle this message very
nicely.
Unfortunately I can not post the code to my fix because portions are
copyrighted... but the basic concept of it is:
1) subclass the edit control
2) trap EM_SHOWBALLOONTIP, if the the tooltip is currently visible on the
screen, disregard this message, otherwise pass it to the original wndproc.
3) trap EM_HIDEBALLOONTIP and set a flag to TRUE before calling the
original wndproc.
4) when this flag is TRUE, block the next InvalidateRect call and set flag
to FALSE.
this will prevent the balloon tooltip from getting destroyed/recreated all
the time and will kill the flicker caused by when it is hidden.
note: with my fix there is one obvious bug here in that if an edit control
has multiple different tips, you will not get updated on the screen if there
is one already there.
I guess I can save the last tip and compare them when I get
EM_SHOWBALLOONTIP messages to see if it is the same one.
"Jeff Partch [MVP]" wrote in message
news:eSD9pCisDHA.3224@tk2msftngp13.phx.gbl...
> "Nobody" wrote in message
> news:dpbwb.10587$Bk1.14@fed1read05...
> > How does one get the position of the cursor in an edit control? I am not
> > talking about the mouse cursor and that is what GetCaretPos() and
> > GetCursorPos() do. I am talking about the blinking vertical line. There
> > doesn't seem to be any way to get it?? I want to be able to get it in
> client
> > or screen coordinates. Thanks!
>
> I participated in a thread about this a couple of weeks ago...
>
>
http://www.google.com/groups?hl=en&l....phx.gbl#link7
>
> ...it wasn't you asking this back then was it? In any event, if you have a
> repro scenario wherein GetCaretPos is broken, I would love to see it and
> have MS look into it. As I said, AFAIK, GetCaretPos is the one and only
API
> provided for this.
>
> --
> Jeff Partch [VC++ MVP]
>
>
-
Re: how to get position of cursor in EDIT control??
"Nobody" wrote in message
news:shcwb.11138$Bk1.9757@fed1read05...
> "Nobody" wrote in message
> news:bgcwb.11124$Bk1.3290@fed1read05...
> > No it wasn't me... I checked out the thread and like the other poster
> said,
> > GetCaretPos and GetCursorPos return the same values. I am running on XP
> with
> > comctl6 if that makes a difference.
> >
> > I did however find a different function a few moments ago that returns
the
> > correct position. GetGUIThreadInfo does the trick.
> By the way, I had subclassed an edit control and was calling this when I
got
> a EM_SHOWBALLOONTIP message.
>
Ahh, GetGUIThreadInfo -- learn something new every day.
I'm still curious
why GetCaretPos works for me, and not you two guys. Is there anything
special about the nature of your implementation: cross-thread,
cross-process, some sort of hook? What do you pass as the 'idThread'
parameter? I'm probably not smart enough to understand it, but if an
explanation can be had, I'd welcome it. And whatever the reason, it seems
like there ought to be some sort of remark in the GetCaretPos documentation.
--
Jeff Partch [VC++ MVP]
-
Re: how to get position of cursor in EDIT control??
"Nobody" wrote in message
news:Wqdwb.11649$Bk1.1112@fed1read05...
> Jeff,
>
> This whole issue is only a part of a bigger problem I was having with a
bug
> in XP that you might want to point out to MS.
>
> Basically, if you have an edit control with the ES_NUMBER on XP and you
type
> an invalid character like a letter, etc. XP shows a balloon tooltip
telling
> you only numbers are acceptable through the EM_SHOWBALLOONTIP message. I
> think its a nifty little thing.
>
> Anyways, there is a huge bug in there somewhere that causes whole dialogs
> and windows to redraw like mad.
>
> For example, stick an edit control on a property sheet, give it the
> ES_NUMBER style, then hold down the 'A' key and the entire property sheet
> will flicker like crazy.
Thanks, N. That is horrible. I was able to repro it in seconds. It seems
like every week, some new theme related behavior (bug) comes up. FWIW, I'll
definitely pass it on to MS.
--
Jeff Partch [VC++ MVP]
-
Re: how to get position of cursor in EDIT control??
Nope, it was a straight MFC dialog application straight out of the wizard
(with the comctl 6.0 manifest). I threw an edit control on the dialog,
subclassed it (of the SetWindowLong(GWL_WNDPROC) variety) and called
GetCaretPos when I got EM_SHOWBALLOONTIP messages.
I'm running VS 2003.NET on XP with all the latest patches.
For the GetGUIThreadInfo, I am passing in the result of GetCurrentThreadId()
which assumes you are calling the function from your main GUI thread. You
can also pass in 0 and it will assume you want the foreground thread which
is OK I guess, since you'll only ever have one caret active at a time and
that'll be in the foreground thread.
> Ahh, GetGUIThreadInfo -- learn something new every day.
I'm still
curious
> why GetCaretPos works for me, and not you two guys. Is there anything
> special about the nature of your implementation: cross-thread,
> cross-process, some sort of hook? What do you pass as the 'idThread'
> parameter? I'm probably not smart enough to understand it, but if an
> explanation can be had, I'd welcome it. And whatever the reason, it seems
> like there ought to be some sort of remark in the GetCaretPos
documentation.
-
Re: how to get position of cursor in EDIT control??
"Nobody" wrote in message
news:wcewb.11945$Bk1.5185@fed1read05...
> Nope, it was a straight MFC dialog application straight out of the wizard
> (with the comctl 6.0 manifest). I threw an edit control on the dialog,
> subclassed it (of the SetWindowLong(GWL_WNDPROC) variety) and called
> GetCaretPos when I got EM_SHOWBALLOONTIP messages.
>
> I'm running VS 2003.NET on XP with all the latest patches.
>
> For the GetGUIThreadInfo, I am passing in the result of
GetCurrentThreadId()
> which assumes you are calling the function from your main GUI thread. You
> can also pass in 0 and it will assume you want the foreground thread which
> is OK I guess, since you'll only ever have one caret active at a time and
> that'll be in the foreground thread.
That seems pretty straightforward. I don't recall whether I ran my test with
a manifest or not (probably not as CEditView is broken with a manifest), but
I'll try it again later using your description. After looking at it though,
the only difference I can see in the implementation of GetGUIThreadInfo and
GetCaretPos is when the calling thread is different than the thread that
created the caret window *and* the window has the CS_OWNDC style. Is that
latter condition ever true for an EDIT control? Otherwise, they both seem to
pull the caret's x & y from the same place in the same way (and which is
seemingly not the same place GetCursorPos gets its position from). I might
have to try and recruit some help from the brain-trust on this one. 
--
Jeff Partch [VC++ MVP]
-
Re: how to get position of cursor in EDIT control??
"Nobody" wrote in message
news:wcewb.11945$Bk1.5185@fed1read05...
> Nope, it was a straight MFC dialog application straight out of the wizard
> (with the comctl 6.0 manifest). I threw an edit control on the dialog,
> subclassed it (of the SetWindowLong(GWL_WNDPROC) variety) and called
> GetCaretPos when I got EM_SHOWBALLOONTIP messages.
>
> I'm running VS 2003.NET on XP with all the latest patches.
>
> For the GetGUIThreadInfo, I am passing in the result of
GetCurrentThreadId()
> which assumes you are calling the function from your main GUI thread. You
> can also pass in 0 and it will assume you want the foreground thread which
> is OK I guess, since you'll only ever have one caret active at a time and
> that'll be in the foreground thread.
Okay, I've got the VC2003 wizard generated dialog app with a manifest
running on XPSP1 and all critical updates. I subclass the ES_NUMBER edit
control using SetWindowLong and this WNDPROC...
LRESULT
CALLBACK
EditSubclassProc(
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
LRESULT lRet = 0;
switch (uMsg)
{
case EM_SHOWBALLOONTIP:
{
POINT pointCaret, pointCursor;
if (GetCaretPos(&pointCaret) &&
GetCursorPos(&pointCursor))
{
TRACE(_T("Caret (%d, %d) : Cursor (%d, %d)\n"),
pointCaret.x, pointCaret.y,
pointCursor.x, pointCursor.y);
GUITHREADINFO gti;
gti.cbSize = sizeof(gti);
if (GetGUIThreadInfo(
GetCurrentThreadId(), >i))
{
TRACE(_T("\tGui (%d, %d)\n"),
gti.rcCaret.left, gti.rcCaret.top);
}
}
// Fall through
}
default:
{
lRet = CallWindowProc(
(WNDPROC)(LONG_PTR)GetClassLongPtr(
hWnd, GCLP_WNDPROC), hWnd, uMsg,
wParam, lParam);
}
}
return lRet;
}
....and in the trace output I get this...
Caret (4, 1) : Cursor (439, 207)
Gui (4, 1)
....GetCaretPos and GetGUIThreadInfo return the same position and not what
GetCursorPos is returning. What are we doing differently?
--
Jeff Partch [VC++ MVP]
-
Re: how to get position of cursor in EDIT control??
Well darn it! After I resolved my flicker problem, I deleted my test
project... I just tried to recreate it.. subclass the edit control, etc in
the same way that I did before and now GetCaretPos is working. Weird!
Obviously there is something here because I am not the only person who has
run into this, but I don't know what caused it and I can't recreate it
.
On the other hand, it could have been a bug in the sample somewhere... too
bad I deleted it... oops.
"Jeff Partch [MVP]" wrote in message
news:edF8JcjsDHA.536@tk2msftngp13.phx.gbl...
> "Nobody" wrote in message
> news:wcewb.11945$Bk1.5185@fed1read05...
> > Nope, it was a straight MFC dialog application straight out of the
wizard
> > (with the comctl 6.0 manifest). I threw an edit control on the dialog,
> > subclassed it (of the SetWindowLong(GWL_WNDPROC) variety) and called
> > GetCaretPos when I got EM_SHOWBALLOONTIP messages.
> >
> > I'm running VS 2003.NET on XP with all the latest patches.
> >
> > For the GetGUIThreadInfo, I am passing in the result of
> GetCurrentThreadId()
> > which assumes you are calling the function from your main GUI thread.
You
> > can also pass in 0 and it will assume you want the foreground thread
which
> > is OK I guess, since you'll only ever have one caret active at a time
and
> > that'll be in the foreground thread.
>
> That seems pretty straightforward. I don't recall whether I ran my test
with
> a manifest or not (probably not as CEditView is broken with a manifest),
but
> I'll try it again later using your description. After looking at it
though,
> the only difference I can see in the implementation of GetGUIThreadInfo
and
> GetCaretPos is when the calling thread is different than the thread that
> created the caret window *and* the window has the CS_OWNDC style. Is that
> latter condition ever true for an EDIT control? Otherwise, they both seem
to
> pull the caret's x & y from the same place in the same way (and which is
> seemingly not the same place GetCursorPos gets its position from). I might
> have to try and recruit some help from the brain-trust on this one. 
> --
> Jeff Partch [VC++ MVP]
>
>
-
Re: how to get position of cursor in EDIT control??
As I said in another post in the thread... my bad... after I got rid of the
flicker in the balloon tip thing, I deleted the test project. I tried to
re-create it, but I couldn't get the wrong GetCaretPos() this time. Usually
my test projects are messy and sloppy and quickly done until I solve the
problem... I'm thinking perhaps I messed it up somewhere... but that
doesn't explain what happened with the other guy.
I could have sworn I went over the GetCaretPos() portion of the code with a
fine tooth comb, but maybe not...
Sorry for wasting your time on this...
"Jeff Partch [MVP]" wrote in message
news:u8yVc9jsDHA.3436@tk2msftngp13.phx.gbl...
> "Nobody" wrote in message
> news:wcewb.11945$Bk1.5185@fed1read05...
> > Nope, it was a straight MFC dialog application straight out of the
wizard
> > (with the comctl 6.0 manifest). I threw an edit control on the dialog,
> > subclassed it (of the SetWindowLong(GWL_WNDPROC) variety) and called
> > GetCaretPos when I got EM_SHOWBALLOONTIP messages.
> >
> > I'm running VS 2003.NET on XP with all the latest patches.
> >
> > For the GetGUIThreadInfo, I am passing in the result of
> GetCurrentThreadId()
> > which assumes you are calling the function from your main GUI thread.
You
> > can also pass in 0 and it will assume you want the foreground thread
which
> > is OK I guess, since you'll only ever have one caret active at a time
and
> > that'll be in the foreground thread.
>
> Okay, I've got the VC2003 wizard generated dialog app with a manifest
> running on XPSP1 and all critical updates. I subclass the ES_NUMBER edit
> control using SetWindowLong and this WNDPROC...
>
> LRESULT
> CALLBACK
> EditSubclassProc(
> HWND hWnd,
> UINT uMsg,
> WPARAM wParam,
> LPARAM lParam
> )
> {
> LRESULT lRet = 0;
> switch (uMsg)
> {
> case EM_SHOWBALLOONTIP:
> {
> POINT pointCaret, pointCursor;
> if (GetCaretPos(&pointCaret) &&
> GetCursorPos(&pointCursor))
> {
> TRACE(_T("Caret (%d, %d) : Cursor (%d, %d)\n"),
> pointCaret.x, pointCaret.y,
> pointCursor.x, pointCursor.y);
> GUITHREADINFO gti;
> gti.cbSize = sizeof(gti);
> if (GetGUIThreadInfo(
> GetCurrentThreadId(), >i))
> {
> TRACE(_T("\tGui (%d, %d)\n"),
> gti.rcCaret.left, gti.rcCaret.top);
> }
> }
> // Fall through
> }
> default:
> {
> lRet = CallWindowProc(
> (WNDPROC)(LONG_PTR)GetClassLongPtr(
> hWnd, GCLP_WNDPROC), hWnd, uMsg,
> wParam, lParam);
> }
> }
> return lRet;
> }
>
> ...and in the trace output I get this...
>
> Caret (4, 1) : Cursor (439, 207)
> Gui (4, 1)
>
> ...GetCaretPos and GetGUIThreadInfo return the same position and not what
> GetCursorPos is returning. What are we doing differently?
>
> --
> Jeff Partch [VC++ MVP]
>
>
-
Re: how to get position of cursor in EDIT control??
"Nobody" wrote in message
news:SSgwb.12275$Bk1.3627@fed1read05...
> As I said in another post in the thread... my bad... after I got rid of
the
> flicker in the balloon tip thing, I deleted the test project. I tried to
> re-create it, but I couldn't get the wrong GetCaretPos() this time.
Usually
> my test projects are messy and sloppy and quickly done until I solve the
> problem... I'm thinking perhaps I messed it up somewhere... but that
> doesn't explain what happened with the other guy.
>
> I could have sworn I went over the GetCaretPos() portion of the code with
a
> fine tooth comb, but maybe not...
>
> Sorry for wasting your time on this...
No problem. Like you, I think it's compelling that two different separately
people posted the same issue.
--
Jeff Partch [VC++ MVP]
-
Re: how to get position of cursor in EDIT control??
On Sun, 23 Nov 2003 15:29:10 -0800, "Nobody" wrote:
>How does one get the position of the cursor in an edit control? I am not
>talking about the mouse cursor and that is what GetCaretPos() and
>GetCursorPos() do. I am talking about the blinking vertical line. There
>doesn't seem to be any way to get it?? I want to be able to get it in client
>or screen coordinates. Thanks!
EM_GETSEL will return location of the vertical line, but in text
postion, not screen coordinates. So it doesn't solve the problem you
pose. I mention it just in case it helps solve the problem behind the
one you pose.
>
>
-----------------------------------------
To reply to me, remove the underscores (_) from my email address (and please indicate which newsgroup and message).
Robert E. Zaret
PenFact, Inc.
500 Harrison Ave., Suite 3R
Boston, MA 02118
www.penfact.com
-
Re: how to get position of cursor in EDIT control??
"Nobody" wrote in message
news:Wqdwb.11649$Bk1.1112@fed1read05...
> Jeff,
>
> This whole issue is only a part of a bigger problem I was having with a
bug
> in XP that you might want to point out to MS.
>
> Basically, if you have an edit control with the ES_NUMBER on XP and you
type
> an invalid character like a letter, etc. XP shows a balloon tooltip
telling
> you only numbers are acceptable through the EM_SHOWBALLOONTIP message. I
> think its a nifty little thing.
>
> Anyways, there is a huge bug in there somewhere that causes whole dialogs
> and windows to redraw like mad.
>
I've looked into this issue a bit further, and all of the points you make
about its implementation prove true. It is not clear to me whether the thing
invalidates and updates its entire parent rect for a reason, but it seems
more like just taking the easy way out rather than a thoughtful solution. In
any case, the result is quite unpleasant. One fly in the ointment that is
your sketch of a workaround is that it appears that all of this is done in a
local helper function (the same one that EM_HIDEBALLOONTIP forwards to),
that is called directly as a subroutine. If this is true, then it bypasses
your subclass interception completely. I like the relative simplicity of
your solution though. One other thing I tried that seems a possible
alternative is to give the dialog the WS_CLIPCHILDREN style. This eliminates
the flicker, but at least two control types -- the groupbox and the
CBS_SIMPLE style combobox have documented trouble with it...
http://support.microsoft.com/default...Ben-us%3B79982
http://support.microsoft.com/default...en-us%3B128110
....and there well may be others. What I did was EnumChildWindows in
WM_INITDIALOG, and subclass the groupbox and simple combos (personally, I
never seem to use these combos) with a WindowProc that handles WM_ERASEBKGND
by SelectObject'ing a GetClientRect/hWndParent-sized CreateCompatibleBitmap
into a CreateCompatibleDC, SendMessage'ing a WM_ERASEBKGND to the parent
with this memory dc in the WPARAM, and then BitBlt'ing the control's portion
of it to the source dc from the control's GetWindowRect/ScreenToClient
coords before falling through to the default handler. This of course
requires that the parent does all of its painting in response to
WM_ERASEBKGND, which is what the WC_DIALOG class does by default. It just
sounds more complicated than it really is. 
--
Jeff Partch [VC++ MVP]
-
Re: how to get position of cursor in EDIT control??
Jeff,
Thanks for looking into this...
My thoughts on this are is that there is no reason to invalidate anything.
The OS will automatically invalidate the correct areas when windows are
shown and/or hidden. On the surface, blocking the InvalidateRect caused no
side effects, but as a long time GUI developer, I know this things sometimes
come back to bite you down the line 
Let me try to explain my work around a little more:
1) subclass the edit control to MyEditHookProc() (lives in test.exe)
2) in MyEditHookProc()
trap EM_SHOWBALLOONTIP message
if tooltip is visible, return 1, else pass message to original
wndproc
trap EM_HIDEBALLOONTIP message
bBlockInvalidateRect = TRUE, pass message to original wndproc
trap WM_KEYDOWN message
if tooltip is visible AND key is invalid, return 0, else pass to
original
wndproc. I had to do the key checking in WM_KEYDOWN too
because this is the handler that hides the balloon tip.
3) Using an API hooking class, I install a hook for InvalidateRect() called
MyInvalidateRect()
if bBlockInvalidateRect == TRUE
return TRUE
else
call original function
4) My "IsToolTipVisible" function is kind of a hack, basically, I use
EnumWindows to enumerate the top level windows and look for tooltip windows.
Due to the location of the calls to this function, I am assuming that if
there is a visible tooltip control, then it is the balloon tip. I guess
there can be a few situations where there are multiple visible tooltips
though.
This all seems to be working...
Are you sure you read the code correctly? it seemed to me that Windows was
internally sending an EM_HIDEBALLOONTIP message when ever it hides the tip
instead of calling the local helper function directly. Is this not the case?
I put traces in the EM_HIDEBALLOONTIP handler and it is getting called when
the tooltip is hidden.
P.S. here is another one for you 
1) put a tree control on a property sheet
2) give it the TVS_DISABLEDRAGDROP | TVS_FULLROWSELECT style
3) add some items to it, expand everything so you can fill up as much of the
window as possible to see the effect.
4) position your property sheet on the screen in such a a way that when you
open the start menu, the start menu will overlap the tree control by maybe
1/4" or 1/2" or whatever.
5) open the start menu
6) now WITHOUT closing the start menu or alt-tabbing etc. click on the tree
control in such a way that the selected item changes.
Voila, the start menu will close, the selected item will change, but you
will be missing everything that was under the start menu!
. This is not
only with the start menu, but pretty much with any window that overlaps the
tree control.
If you take off the disabledragdrop style this problem goes away, but that
is because the item selection no longer changes on WM_LBUTTONDOWN, but
rather WM_LBUTTONUP. Weird little bug, the property sheet page is painting
through the tree control. I duplicated this with a stock tree control.
A side note, it appears the non-client area is getting repainted, just not
the client area. You can InvalidateRect() in TVN_SELCHANGE til you are blue
in the face and it wont repaint in this situation
. A simple fix was to
InvalidateRect() in the WM_NCPAINT handler.
Another sidenote, paint messages are gotten just fine, its just getting
garbled somewhere along the line.
> I've looked into this issue a bit further, and all of the points you make
> about its implementation prove true. It is not clear to me whether the
thing
> invalidates and updates its entire parent rect for a reason, but it seems
> more like just taking the easy way out rather than a thoughtful solution.
In
> any case, the result is quite unpleasant. One fly in the ointment that is
> your sketch of a workaround is that it appears that all of this is done in
a
> local helper function (the same one that EM_HIDEBALLOONTIP forwards to),
> that is called directly as a subroutine. If this is true, then it bypasses
> your subclass interception completely. I like the relative simplicity of
> your solution though. One other thing I tried that seems a possible
> alternative is to give the dialog the WS_CLIPCHILDREN style. This
eliminates
> the flicker, but at least two control types -- the groupbox and the
> CBS_SIMPLE style combobox have documented trouble with it...
>
> http://support.microsoft.com/default...Ben-us%3B79982
> http://support.microsoft.com/default...en-us%3B128110
>
> ...and there well may be others. What I did was EnumChildWindows in
> WM_INITDIALOG, and subclass the groupbox and simple combos (personally, I
> never seem to use these combos) with a WindowProc that handles
WM_ERASEBKGND
> by SelectObject'ing a GetClientRect/hWndParent-sized
CreateCompatibleBitmap
> into a CreateCompatibleDC, SendMessage'ing a WM_ERASEBKGND to the parent
> with this memory dc in the WPARAM, and then BitBlt'ing the control's
portion
> of it to the source dc from the control's GetWindowRect/ScreenToClient
> coords before falling through to the default handler. This of course
> requires that the parent does all of its painting in response to
> WM_ERASEBKGND, which is what the WC_DIALOG class does by default. It just
> sounds more complicated than it really is. 
>
> --
> Jeff Partch [VC++ MVP]
>
>
-
Re: how to get position of cursor in EDIT control??
"Nobody" wrote in message
news:uurw3lssDHA.2360@TK2MSFTNGP10.phx.gbl...
> Jeff,
>
> Thanks for looking into this...
>
> My thoughts on this are is that there is no reason to invalidate anything.
> The OS will automatically invalidate the correct areas when windows are
> shown and/or hidden. On the surface, blocking the InvalidateRect caused no
> side effects, but as a long time GUI developer, I know this things
sometimes
> come back to bite you down the line 
Like I say, it's unclear whether this was done for a reason, but I tend to
agree with you. I do recall some years back having to to invalidate/update
some part of the parent for some freakish reason, but think I was able to
y'know -- narrow it down.
>
> Let me try to explain my work around a little more:
>
> 1) subclass the edit control to MyEditHookProc() (lives in test.exe)
>
> 2) in MyEditHookProc()
>
> trap EM_SHOWBALLOONTIP message
> if tooltip is visible, return 1, else pass message to original
> wndproc
This handler destroys the current tooltip (if it still exists), Creates the
new tooltip, subclasses every parent of the edit up to the desktop, and
starts a timer to dismiss the tooltip.
>
> trap EM_HIDEBALLOONTIP message
> bBlockInvalidateRect = TRUE, pass message to original wndproc
Discussed at the end.
>
> trap WM_KEYDOWN message
> if tooltip is visible AND key is invalid, return 0, else pass to
> original
> wndproc. I had to do the key checking in WM_KEYDOWN too
> because this is the handler that hides the balloon tip.
Yep, you're right. This is how the EM_HIDEBALLOONTIP gets routed through the
WindowProc.
>
> 3) Using an API hooking class, I install a hook for InvalidateRect()
called
> MyInvalidateRect()
>
> if bBlockInvalidateRect == TRUE
> return TRUE
> else
> call original function
I've never taken to API hooking, but have often felt the need. Can't say
more. 
>
> 4) My "IsToolTipVisible" function is kind of a hack, basically, I use
> EnumWindows to enumerate the top level windows and look for tooltip
windows.
> Due to the location of the calls to this function, I am assuming that if
> there is a visible tooltip control, then it is the balloon tip. I guess
> there can be a few situations where there are multiple visible tooltips
> though.
Yeah, that makes me a bit nervous too. From memory, I think calling
GetWindowLongPtr/GWL_HWNDPARENT on the tooltip might return the HWND of the
edit.
>
> This all seems to be working...
That's all that really matters. 
>
> Are you sure you read the code correctly? it seemed to me that Windows was
> internally sending an EM_HIDEBALLOONTIP message when ever it hides the tip
> instead of calling the local helper function directly. Is this not the
case?
>
> I put traces in the EM_HIDEBALLOONTIP handler and it is getting called
when
> the tooltip is hidden.
I thought I was, but overlooked the WM_KEYDOWN thing. Sorry about that.
>
> P.S. here is another one for you 
One thing at a time, N!
I've archived this one for later exploration.
--
Jeff Partch [VC++ MVP]
-
Re: how to get position of cursor in EDIT control??
> Like I say, it's unclear whether this was done for a reason, but I tend to
> agree with you. I do recall some years back having to to
>invalidate/update
> some part of the parent for some freakish reason, but think I was able
>to
> y'know -- narrow it down.
I've seen weird things like that, like the tree view thing I mentioned.
> > Let me try to explain my work around a little more:
> >
> > 1) subclass the edit control to MyEditHookProc() (lives in test.exe)
> >
> > 2) in MyEditHookProc()
> >
> > trap EM_SHOWBALLOONTIP message
> > if tooltip is visible, return 1, else pass message to original
> > wndproc
>
> This handler destroys the current tooltip (if it still exists), Creates
the
> new tooltip, subclasses every parent of the edit up to the desktop, and
> starts a timer to dismiss the tooltip.
Thats pretty weird by itself. Why would they subclass every window up to the
desktop? That seems excessive. There are much nicer ways to tell when to
dismiss the tip 
> > 3) Using an API hooking class, I install a hook for InvalidateRect()
> called
> > MyInvalidateRect()
> >
> > if bBlockInvalidateRect == TRUE
> > return TRUE
> > else
> > call original function
>
> I've never taken to API hooking, but have often felt the need. Can't say
> more. 
Yeah, API hooking is pretty dirty, I use it very sparingly. A cleaner way to
do this would be to subclass the parent or grandparent and block the
WM_ERASEBKGND message that way.
I think the reason I chose to do it the API hooking way is that if the edit
control is on a dialog, the dialog (parent) is invalidated, but if its on a
property sheet, its the property sheet (grand parent) thats invalidated. The
API hooking way is generic. I didn't want to have to special case out
various parent windows and how many levels to go up.
This is all for work I am doing on a GUI library, so I need to encapsulate
as much as possible and require as little as possible from the user of the l
ibrary (like adding special case WM_ERASEBKGND handlers to various places).
So far, I have been amazingly successful at keeping all my classes and
custom controls "plug & play" and building on top of native stuff everywhere
so it doesn't break existing code and/or MFC.
> >
> > 4) My "IsToolTipVisible" function is kind of a hack, basically, I use
> > EnumWindows to enumerate the top level windows and look for tooltip
> windows.
> > Due to the location of the calls to this function, I am assuming that if
> > there is a visible tooltip control, then it is the balloon tip. I guess
> > there can be a few situations where there are multiple visible tooltips
> > though.
>
> Yeah, that makes me a bit nervous too. From memory, I think calling
> GetWindowLongPtr/GWL_HWNDPARENT on the tooltip might return the HWND of
the
> edit.
Cool, I'll check that out... if that it is the case, it'll be nicer to just
enumerate the children of the edit control.
Is there any exposed way (even if it is undocumented) to check if the
tooltip is visible? undocumented messages, exported functions, round about
ways of calling the local function, etc?
-
Re: how to get position of cursor in EDIT control??
"Nobody" wrote in message
news:esW$IutsDHA.1512@TK2MSFTNGP10.phx.gbl...
> > Yeah, that makes me a bit nervous too. From memory, I think calling
> > GetWindowLongPtr/GWL_HWNDPARENT on the tooltip might return the HWND of
> the
> > edit.
>
> Cool, I'll check that out... if that it is the case, it'll be nicer to
just
> enumerate the children of the edit control.
Well, I can't get it to work. It must be some old school concept.
>
> Is there any exposed way (even if it is undocumented) to check if the
> tooltip is visible? undocumented messages, exported functions, round about
> ways of calling the local function, etc?
Well, my latest brainstorm is to handle the WM_NOTIFYFORMAT/NF_QUERY in the
edit subclass. One of the very first things the common controls do when they
get created is query their parent about this, and they pass their HWND in
the WPARAM. The edit seem to get this from the balloontip, so it ought to be
a simple question of is this HWND a TOOLTIPS_CLASS, and if so cache it for
later IsWindow testing.
--
Jeff Partch [VC++ MVP]
-
Re: how to get position of cursor in EDIT control??
Upon further thought...
Tooltips have to be WS_POPUP windows, so there isn't going to be any
parent/child relationship between the edit control and tooltip.
The edit control has 4 extra window bytes defined, which I guessed was a
pointer to an internal struct. Examining the pointer, I found the handle to
the tooltip control in there:
LPBYTE lpb = (LPBYTE)GetWindowLong(hWndEdit, 0);
lpb += 0x11c;
DWORD* lpdw = (DWORD*)lpb;
*lpdw will be non zero if the tooltip is visible.
This is a much cleaner way then the EnumWindows, but a lot less reliable. MS
is generally pretty good about maintaining backwards compatibility in APIs
and structs, but since this is an internal thing, it can completely change
in any patch or service pack or update breaking my code.
I also put a trace in my wndproc and saw no weird messages coming through.
"Jeff Partch [MVP]" wrote in message
news:ObA8dfvsDHA.3436@tk2msftngp13.phx.gbl...
> "Nobody" wrote in message
> news:esW$IutsDHA.1512@TK2MSFTNGP10.phx.gbl...
> > > Yeah, that makes me a bit nervous too. From memory, I think calling
> > > GetWindowLongPtr/GWL_HWNDPARENT on the tooltip might return the HWND
of
> > the
> > > edit.
> >
> > Cool, I'll check that out... if that it is the case, it'll be nicer to
> just
> > enumerate the children of the edit control.
>
> Well, I can't get it to work. It must be some old school concept.
>
> >
> > Is there any exposed way (even if it is undocumented) to check if the
> > tooltip is visible? undocumented messages, exported functions, round
about
> > ways of calling the local function, etc?
>
> Well, my latest brainstorm is to handle the WM_NOTIFYFORMAT/NF_QUERY in
the
> edit subclass. One of the very first things the common controls do when
they
> get created is query their parent about this, and they pass their HWND in
> the WPARAM. The edit seem to get this from the balloontip, so it ought to
be
> a simple question of is this HWND a TOOLTIPS_CLASS, and if so cache it for
> later IsWindow testing.
> --
> Jeff Partch [VC++ MVP]
>
>