Solved

PROBLEM: Overriding of SHIFT in webbrowser control

Posted on 2004-04-29
18
644 Views
Last Modified: 2013-11-20
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.
0
Comment
Question by:mrwad99
  • 7
  • 7
  • 3
  • +1
18 Comments
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 10949772
What happens if you remove the MK_SHIFT bit from the pMsg->wParam and let the default behaviour take place
0
 
LVL 19

Author Comment

by:mrwad99
ID: 10949840
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.
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 10950122
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
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 10950133
ahh :)

now I saw that AndyAinscow told you to do the same ... you just misunderstood him I think ...
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 10950194
You have stripped out the shift bit in the pMsg->wParam have you?
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 10950232
Well, mrwad99 wrote
>if (pMsg->message == WM_LBUTTONDOWN && pMsg->wParam) {
I guess he just stripped out the WM_SHIFT from the 'if' :)
0
 
LVL 19

Author Comment

by:mrwad99
ID: 10950287
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.
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 10950336
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
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 10950352
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
}
//...
}
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 19

Author Comment

by:mrwad99
ID: 10950543
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
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 10950860
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 ...
0
 
LVL 19

Author Comment

by:mrwad99
ID: 10951432
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

??
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 10951612
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
0
 
LVL 19

Author Comment

by:mrwad99
ID: 10951721
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.
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 10951954
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 ...

0
 
LVL 19

Author Comment

by:mrwad99
ID: 10952327
>> 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...
0
 
LVL 3

Accepted Solution

by:
kklai72 earned 500 total points
ID: 10956473
Instead of modify pMsg->wParam, you can clear the keyboard state, try the followings

BOOL CWebBrowser2::PreTranslateMessage(MSG *pMsg)
{
      if (pMsg->message==WM_LBUTTONUP && pMsg->wParam & MK_SHIFT) {
            m_bNewTab = TRUE;
            BYTE p[256];
            ::GetKeyboardState(p);
            p[VK_SHIFT]=0;
            ::SetKeyboardState(p);
            //TRACE("%x\n",p[VK_SHIFT]);
      }
      return CWnd::PreTranslateMessage(pMsg);
}
0
 
LVL 19

Author Comment

by:mrwad99
ID: 10958234
Absolutely brilliant.  Many thanks !
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
repeatSeparator  java  challenge 13 56
WinWaitActive parameters 12 31
viewing source code from eclipse 13 74
Window placement 17 65
In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008.  These same feature are in the MFC libraries that come with Visual …
Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

26 Experts available now in Live!

Get 1:1 Help Now