Link to home
Start Free TrialLog in
Avatar of mrwad99
mrwad99Flag for United Kingdom of Great Britain and Northern Ireland

asked on

PROBLEM: Overriding of SHIFT in webbrowser control

This is related to a previous question (http:Q_20966269.html) where I asked how to prevent shift->left click on a link opening a new IE window displaying the link when using a webbrowser control in my app.  I got the answer, but am now finding a new problem:

Thanks to the solution posted at the question linked to above, In my app (dialogue based for the sake of argument) I have

BOOL CContainerDlg::PreTranslateMessage(MSG* pMsg)
{
///...other tests

if (pMsg->message == WM_LBUTTONDOWN && pMsg->wParam&MK_SHIFT) {
      m_bNewTab = TRUE;
      return TRUE;
}
//...
}

which traps all shift->left click combinations.  But the issue is, I need to determine the URL that was going to be navigated to (if it was a hyperlink that was clicked on) so my app can handle that.  This was previously done in OnBeforeNavigate().  

So how can I still allow OnBeforeNavigate to be called, *without opening a new IE window* ?  I thought I could post an 'OnBeforeNavigate' message or similar, but don't really know how to do this.

Any info greatly appreciated.
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

What happens if you remove the MK_SHIFT bit from the pMsg->wParam and let the default behaviour take place
Avatar of mrwad99

ASKER

With:

if (pMsg->message == WM_LBUTTONDOWN && pMsg->wParam) {

nothing happens

with

if (pMsg->message == WM_LBUTTONDOWN) {

nothing happens.  This will be as a result of the browser getting the WM_LBUTTON down message immediately when the usr clicks a hyperlink.  No further processing is done due to the

return TRUE;

...however, without this a new browser window is opened to display the link; not what I want.
hm ... I'm not sure if I understand your problem correctly ... as I understand it you simply want that clicking with hold SHIFT does the same as without ...

In this case you could simply do something like:

BOOL CContainerDlg::PreTranslateMessage(MSG* pMsg)
{
///...other tests

if (pMsg->message == WM_LBUTTONDOWN && pMsg->wParam&MK_SHIFT)
{
 pMsg->wParam &= ~MK_SHIFT;  // remove the shift-flag from the message ...
}
//...
}

hope that helps,

ZOPPO
ahh :)

now I saw that AndyAinscow told you to do the same ... you just misunderstood him I think ...
You have stripped out the shift bit in the pMsg->wParam have you?
Well, mrwad99 wrote
>if (pMsg->message == WM_LBUTTONDOWN && pMsg->wParam) {
I guess he just stripped out the WM_SHIFT from the 'if' :)
Avatar of mrwad99

ASKER

Right, I am not sure that I understood Andy either, but I am not sure that anyone understands the problem.  It is a little difficult to explain, so I am going to be verbose now in the hope that someone can help.

My app is the MDI version of msdn.microsoft.com/msdnmag/issues/0600/Wicked/

You can see that this app uses a custom CTabView class.  Now, to begin with my app has one tab containing an ActiveX webbrowser control that displays web pages.  The idea is that when the user clicks a link whilst holding down the shift key, my app opens a new tab to display the page.  The current behaviour is that a new IE window is opened hence meaning my app loses the focus (literally).  What I asked in the previous question told me how to to trap the shift->click combination, but at the time I did not realise that no more messages would be sent due to returning TRUE.  

This is a problem since to obtain the URL that the user clicked on means trapping the OnBeforeNavigate message generated by the browser control:

OnBeforeNavigate2Explorer1(LPDISPATCH pDisp, VARIANT FAR* URL, VARIANT FAR* Flags, VARIANT FAR* TargetFrameName, VARIANT FAR* PostData, VARIANT FAR* Headers, BOOL FAR* Cancel)

Where I get hold of the URL to be navigated to via something like URL->bStrVal.  Hence all I have to do is open a new tab and navigate the browser control of that tab to this URL.  But this cannot happen, since as soon as I return TRUE from PreTranslateMessage (as above, that traps the shift->click combo) no more messages are apparenly sent, let alone BeforeNavigate one. (I have traced, ran to the "return TRUE" in PreTranslateMessage then told the compiler to run to the cursor - which I have placed in OnBeforeNavigate - and it does not get there unless I click a hyperlink *without holding down shift*).

So in essence I just need to stop IE opening a new window on shift->click *but still get hold of the OnBeforeNavigate message*.  

I have doubled the points since I forsee this being a tough one.
ok ... so I think this should do it:

BOOL CContainerDlg::PreTranslateMessage(MSG* pMsg)
{
///...other tests

if (pMsg->message == WM_LBUTTONDOWN && pMsg->wParam&MK_SHIFT)
{
 m_bNewTab = TRUE;
 pMsg->wParam &= ~MK_SHIFT;  // remove the shift-flag from the message ...
}
//...
}

this will set the m_bNewTab = TRUE; which I think you check later to see if SHIFT was pressed, then it removes the SHIFT-bit from the
message and passes it to the default message processing, so the message is manipulated to be a simple WM_LBUTTONDOWN without SHIFT

ZOPPO
Hi Zoppo - you could be right there.

This is what I meant (altough one could use a bitwise modifier if one wished)

BOOL CContainerDlg::PreTranslateMessage(MSG* pMsg)
{
///...other tests

if (pMsg->message == WM_LBUTTONDOWN && pMsg->wParam&MK_SHIFT) {
     pMsg->wParam -= MK_SHIFT;   //REMOVE THE BIT SETTING THE SHIFT
    //DO NOT RETURN HERE - let the default behaviour take place
}
//...
}
Avatar of mrwad99

ASKER

Sorry folks but that still does not work.  Shift->Click still opens a new browser window:

http://mr_wad_99.europe.webmatrixhosting.net/Gui4UnexTEST.zip
Well, it of course maybe that the control check the pressed-state of the SHIFT key in another way ...

you could simulate a temporary release of SHIFT while the message is processed, i.e.

BOOL CContainerDlg::PreTranslateMessage(MSG* pMsg)
{
///...other tests
BOOL bShiftReleased = FALSE;
if (pMsg->message == WM_LBUTTONDOWN && pMsg->wParam&MK_SHIFT)
{
 m_bNewTab = TRUE;
 pMsg->wParam &= ~MK_SHIFT;  // remove the shift-flag from the message ...
 bShiftReleased = TRUE;
 keybd_event( VK_SHIFT, 0, KEYEVENTF_KEYUP, 0 ); // simulate SHIFT release
}

BOOL bRet = CHtmlDialog::PreTranslateMessage( pMsg );

if ( FALSE != bShiftReleased )
 keybd_event( VK_SHIFT, 0, 0, 0 ); // simulate SHIFT pressed again ...

//...
}

ZOPPO


PS: The link you posted above doesn't work for me ...
Avatar of mrwad99

ASKER

I am sure that the link above works; try right clicking it and "save target as".

I am not sure what the idea was in the last post of yours; I have tried no end of combinations to simulate the shift key press/different combinations of 'if' tests etc but it will not work.  I think that the answer lies in what you originally posted, removing the SHIFT bit from the message but cannot see what else needs to be done or why this is not working.

Also,

BOOL bRet = CHtmlDialog::PreTranslateMessage( pMsg );

VC++ complained that

'CHtmlDialog' : is not a class or namespace name

??
sorry, should have been 'CDHtmlDialog'

and, also sorry, but the link doesn't work with any of my browsers ...

and, the idea of my last post is following: It may be that the IE control encapsulated by CDHtmlDialog uses another
way to determine whether the SHIFT key is pressed ... it maybe that it doesn't use the MK_SHIFT passed with the
sent message. It could be that it uses something like GetKeyState to determine the state of the SHIFT key so it
wouldn't matter to reset the SHIFT flag in the passed message ...

ZOPPO
Avatar of mrwad99

ASKER

OK I cannot look into that explanation as MSVC++ (6.0, latest SP) moans about CDHtmlDialog saying it cannot find it.  When I look it up on MSDN it says I need to include afxdhtml.h; doing so makes the compiler moan that it cannot find that header file.

Is there no way of getting control to pass to OnBeforeNavigate after returning TRUE from PreTranslateMessage or even sending a message that would get to there ?  I cannot see why the removal of the SHIFT flag fails to work as well.

I cannot see why that link does not work, it does for me.  If you wanted to look into it it is just a case of creating a dialog app, sticking a browser control on it and going from there.  But 500 points may not be enough to go into that much effort...

Cheers so far; it is of course appreciated.
ok ... you can check out MSDN about CDHtmlDialog using this link: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/vcrefcdhtmldialog.asp

on the other hand I just guessed that CDHtmlDialog is the base class of your dialog ... of course I'm not sure about this.

Unfortunateley I can't tell you if there is any other way to do what you need: I'm simply have no experience using these IE controls, sorry ...

>I cannot see why the removal of the SHIFT flag fails to work as well.
Well, as told, it's simply not guaranteed that the message handler of the control does take care about the SHIFT flag ... there are other possibilities
to find out whether a key is pressed, i.e. GetKeyState, GetAsyncKeyState, GetKeyboardState or simply by handling WM_KEYDOWN and WM_KEYUP message
for VK_SHIFT ...

And, to the last point: It's not the points which are not enough, sorry, it's my time ... in the meantime I have a job to do ;o) ...

Would be interesting if AndyAinscow can use the link ... I promise it doesn't work here ...

Avatar of mrwad99

ASKER

>> in the meantime I have a job to do ;o) ...

Yeah I fully understand that and really appreciate all help I have ever been given on EE; I am aware that others have spent their time helping and I really do regard that highly.  Thanks.

Well, lets see if anyone else has other ideas...
ASKER CERTIFIED SOLUTION
Avatar of kklai72
kklai72

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of mrwad99

ASKER

Absolutely brilliant.  Many thanks !