How to pass IWebBrowser2::Navigate2 arguments? - c++

I want to implement Internet Explorer webview control on my window.
I found this answer, on how to do that.
There is a problem: Navigate2 method from the answer is different from the headers I have. In the posters’s code, seems it has only one argument, and maybe others are by default, but I have 5 arguments with the stupidest thing I have ever met - VARIANT type variables (also, in poster’s code it is _variant_t which is undefined for me).
Probably I will never understand the sEiFe logic, why to make instead of Navigate2(wchar_t *,...) cool stuff VARIANT * (I know about Navigate method), but can anyone provide an example of calling that method.
This full code
#include <Windows.h>
#include <Ole2.h>
#include "resource.h"
#include <iostream>
#include <atlbase.h> //activex
#include <atlwin.h> //windows
#include <atlcom.h>
#include "exdisp.h"
#include <comutil.h>
#pragma comment(lib, "comsuppw.lib")
//This will load the browser dll then library and will generate headers
//All the declarations will be in the namespace SHDocVw
//#import "shdocvw.dll"
using namespace std;
class CMyDialog : public CAxDialogImpl<CMyDialog>
{
public:
enum { IDD = IDD_DIALOG1 };
BEGIN_MSG_MAP(CMyDialog)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_HANDLER(IDCANCEL, BN_CLICKED, OnBnCancel)
COMMAND_HANDLER(IDOK, BN_CLICKED, OnBnOk)
END_MSG_MAP()
CComPtr<IWebBrowser2> ctrl;
LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// Do some initialization code
HRESULT hr;
//IDC_EXPLORER_TEST is the ID of your control
GetDlgControl(IDC_EXPLORER_TEST, __uuidof(ctrl), (void**)&ctrl);
VARIANT address;
address.vt = VT_BSTR;
address.bstrVal = SysAllocString(L"google.com");
VARIANT empty;
empty.vt = VT_EMPTY;
hr = ctrl->Navigate2(&address, &empty, &empty, &empty, &empty);
SysFreeString(address.bstrVal);
/*
Also fails
_variant_t a = SysAllocString(L"google.com");
VARIANT f;
f.vt = VT_I2;
f.iVal = navBrowserBar;
_variant_t fr = SysAllocString(L"_self");
_variant_t h = SysAllocString(L" ");
hr = ctrl->Navigate2(&a, &f, &fr, &h, &h);
*/
LRESULT res = CAxDialogImpl<CMyDialog>::OnInitDialog(uMsg, wParam, lParam, bHandled);
return 0;
}
public:
LRESULT OnBnCancel(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
EndDialog(IDCANCEL);
return 0;
}
LRESULT OnBnOk(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
EndDialog(IDOK);
return 0;
}
};
CComModule _Module;
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
CMyDialog dlg;
dlg.DoModal();
return 0;
}
Returns an exception at method call because of 0x0 read violation.

It appears that you failed to check if GetDlgControl succeeded. When it fails, ctrl has an unspecified value and might be null.
Of course, that leaves the question why it would fail, but that's another issue.

Related

Support modal and modeless dialogs in ActiveX controls

I want to create an ActiveX control supporting modal and modeless dialogs, which can be used in multiple IE9~IE11 tab pages at the same time. It means a pop-up of dialog box by the ActiveX control within current IE tab page won't prevent us from switching to other IE tab pages and these dialogs only appear in current IE tab page. First I created an ATL Dynamic-link library (DLL) application named as AtlActiveX using ATL/C++ by Visual Studio 2010. Then add an ActiveX control named as AtlActiveXCtl, specifying Allow merging of proxy/stub code and IObjectWithSite (IE object support) options. And then add a dialog resource named as IDD_DIALOG1. If not mentioned here, other options are left as default. Since windows/dialogs need to be supported, the member variable m_bWindowOnly has to be assigned in CAtlActiveXCtl constructor. After that add a message handler for WM_CREATE message, displaying dialog boxes in OnCreate function. The full code of AtlActiveXCtl.h is attached below.
I referred to another question Display Modal Dialog Box with ActiveX on StackOverflow. Three pop-up dialogs are tested in OnCreate() function.
#pragma once
#include "resource.h"
#include <atlctl.h>
#include "AtlActiveX_i.h"
using namespace ATL;
// Modeless dialog
class CModelessDialog : public CDialogImpl<CModelessDialog>
{
public:
enum { IDD = IDD_DIALOG1 };
BEGIN_MSG_MAP(CModelessDialog)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_CLOSE, OnClose)
END_MSG_MAP()
LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL &)
{
return 0;
}
LRESULT OnClose(UINT, WPARAM, LPARAM, BOOL &)
{
DestroyWindow();
return 0;
}
};
// CAtlActiveXCtl
class ATL_NO_VTABLE CAtlActiveXCtl :
public CComObjectRootEx<CComSingleThreadModel>,
public IDispatchImpl<IAtlActiveXCtl, &IID_IAtlActiveXCtl, &LIBID_AtlActiveXLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
public IOleControlImpl<CAtlActiveXCtl>,
public IOleObjectImpl<CAtlActiveXCtl>,
public IOleInPlaceActiveObjectImpl<CAtlActiveXCtl>,
public IViewObjectExImpl<CAtlActiveXCtl>,
public IOleInPlaceObjectWindowlessImpl<CAtlActiveXCtl>,
public ISupportErrorInfo,
public IObjectWithSiteImpl<CAtlActiveXCtl>,
public IQuickActivateImpl<CAtlActiveXCtl>,
public IDataObjectImpl<CAtlActiveXCtl>,
public IProvideClassInfo2Impl<&CLSID_AtlActiveXCtl, NULL, &LIBID_AtlActiveXLib>,
public CComCoClass<CAtlActiveXCtl, &CLSID_AtlActiveXCtl>,
public CComControl<CAtlActiveXCtl>
{
public:
CAtlActiveXCtl()
{
m_bWindowOnly = 1;
}
DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE |
OLEMISC_CANTLINKINSIDE |
OLEMISC_INSIDEOUT |
OLEMISC_ACTIVATEWHENVISIBLE |
OLEMISC_SETCLIENTSITEFIRST
)
DECLARE_REGISTRY_RESOURCEID(IDR_ATLACTIVEXCTL)
BEGIN_COM_MAP(CAtlActiveXCtl)
COM_INTERFACE_ENTRY(IAtlActiveXCtl)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IViewObjectEx)
COM_INTERFACE_ENTRY(IViewObject2)
COM_INTERFACE_ENTRY(IViewObject)
COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
COM_INTERFACE_ENTRY(IOleInPlaceObject)
COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
COM_INTERFACE_ENTRY(IOleControl)
COM_INTERFACE_ENTRY(IOleObject)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
COM_INTERFACE_ENTRY(IQuickActivate)
COM_INTERFACE_ENTRY(IDataObject)
COM_INTERFACE_ENTRY(IProvideClassInfo)
COM_INTERFACE_ENTRY(IProvideClassInfo2)
COM_INTERFACE_ENTRY(IObjectWithSite)
END_COM_MAP()
BEGIN_PROP_MAP(CAtlActiveXCtl)
PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
// Example entries
// PROP_ENTRY_TYPE("Property Name", dispid, clsid, vtType)
// PROP_PAGE(CLSID_StockColorPage)
END_PROP_MAP()
BEGIN_MSG_MAP(CAtlActiveXCtl)
CHAIN_MSG_MAP(CComControl<CAtlActiveXCtl>)
DEFAULT_REFLECTION_HANDLER()
MESSAGE_HANDLER(WM_CREATE, OnCreate)
END_MSG_MAP()
// Handler prototypes:
// LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
// LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
// LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
// ISupportsErrorInfo
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
{
static const IID* const arr[] =
{
&IID_IAtlActiveXCtl,
};
for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i], riid))
return S_OK;
}
return S_FALSE;
}
// IViewObjectEx
DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)
// IAtlActiveXCtl
public:
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
IOleInPlaceFrame *pOleInPlaceFrame = NULL;
IOleInPlaceUIWindow *pOleInPlaceUIwindow = NULL;
IOleInPlaceSite *pOleInPlaceSite = NULL;
OLEINPLACEFRAMEINFO oleInPlaceFrameInfo;
oleInPlaceFrameInfo.cb = sizeof(oleInPlaceFrameInfo);
HRESULT hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSite, (LPVOID *)&pOleInPlaceSite);
if (hr != S_OK)
return S_OK;
RECT rc1, rc2;
hr = pOleInPlaceSite->GetWindowContext(&pOleInPlaceFrame, &pOleInPlaceUIwindow, &rc1, &rc2, &oleInPlaceFrameInfo);
{
HWND hWndTop = NULL;
pOleInPlaceSite->GetWindow(&hWndTop);
pOleInPlaceFrame->EnableModeless(TRUE);
::EnableWindow(hWndTop, FALSE);
//[1] Message box, cannot switch tab page
MessageBox(L"Hello, world!", L"MSG", MB_OK);
//[2] Modal dialog, cannot switch tab page
CSimpleDialog<IDD_DIALOG1> dlg;
dlg.DoModal(hWndTop);
//[3] Modeless dialog, can switch tab page, but always stays on top of IE browser
CModelessDialog *pDlg = new CModelessDialog;
pDlg->Create(hWndTop);
pDlg->ShowWindow(SW_SHOWNORMAL);
pOleInPlaceFrame->EnableModeless(FALSE);
::EnableWindow(hWndTop, TRUE);
}
return 0;
}
HRESULT OnDraw(ATL_DRAWINFO& di)
{
RECT& rc = *(RECT*)di.prcBounds;
// Set Clip region to the rectangle specified by di.prcBounds
HRGN hRgnOld = NULL;
if (GetClipRgn(di.hdcDraw, hRgnOld) != 1)
hRgnOld = NULL;
bool bSelectOldRgn = false;
HRGN hRgnNew = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
if (hRgnNew != NULL)
bSelectOldRgn = (SelectClipRgn(di.hdcDraw, hRgnNew) != ERROR);
Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom);
SetTextAlign(di.hdcDraw, TA_CENTER|TA_BASELINE);
LPCTSTR pszText = _T("AtlActiveXCtl");
TextOut(di.hdcDraw,
(rc.left + rc.right) / 2,
(rc.top + rc.bottom) / 2,
pszText,
lstrlen(pszText));
if (bSelectOldRgn)
SelectClipRgn(di.hdcDraw, hRgnOld);
return S_OK;
}
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
};
OBJECT_ENTRY_AUTO(__uuidof(AtlActiveXCtl), CAtlActiveXCtl)
Modal and modeless dialogs need to be supported in ActiveX controls within IE11 tab pages just like in plain Win32 GUI applications. Can anyone kindly help me to solve this problem?

C++ Unknown override specifier when using function in callback

I'm working with C++ and the Windows API now for just a little while. I've never used a callback in C++ since yesterday, when the Windows API required me to do so for installing a low level mouse event hook (link to hook function). To keep my code a little cleaner I wanted to outsource some code to a function and then I ran into a problem that I don't understand. I think it has to do something with me not totally understanding the callback scope or something like that. My code looks like this and I use C++11 and VS2017:
MouseHandler.h
#ifndef __MOUSEHANDLER_H_INCLUDED__
#define __MOUSEHANDLER_H_INCLUDED__
#include <Windows.h>
class MouseHandler
{
private:
public:
static _bstr_t coordinatesToString(POINT point);
MouseHandler();
~MouseHandler();
};
#endif // !__MOUSEHANDLER_H_INCLUDED__
MouseHandler.cpp
#include "stdafx.h"
#include "MouseHandler.h"
#include <comutil.h>
#include <string>
using namespace std;
HHOOK mouseHook = NULL;
_bstr_t MouseHandler::coordinatesToString(POINT point)
{
_bstr_t coordinates = "(";
_bstr_t xcoordinate = to_string(point.x).c_str();
_bstr_t ycoordinate = to_string(point.y).c_str();
coordinates += xcoordinate + "," + ycoordinate + ")";
return coordinates;
}
LRESULT CALLBACK MouseHookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
MSLLHOOKSTRUCT event = *((MSLLHOOKSTRUCT *)lParam);
if (nCode == HC_ACTION)
{
_bstr_t message = "Mouse action happened at position: ";
_bstr_t mouseCoordinates = MouseHandler::coordinatesToString(event.pt);
message += mouseCoordinates;
}
return CallNextHookEx(mouseHook, nCode, wParam, lParam);
}
MouseHandler::MouseHandler()
{
mouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookCallback, NULL, 0);
while (GetMessage(NULL, NULL, 0, 0) != 0);
}
MouseHandler::~MouseHandler()
{
}
When I try to compile I get the error C3646 'coordinatesToString': unknown override specifier. I searched up and down and asked my colleagues, but I couldn't get help with this, so I hope someone here can help me. Thanks in advance!
Make sure you specify the correct type of data.
to_string((long double)point.x).c_str();
Load the lib.
#pragma comment (lib, "comsuppw.lib")
or
#pragma comment (lib, "comsuppwd.lib")
Include comutil.h to the header CMouseHandler.h.
I tested your code in VS2010 C++ on Win10 1803 x64.
CMouseHandler.h
#pragma once
#include <Windows.h>
#include <comutil.h>
#include <string>
using namespace std;
#pragma comment (lib, "comsuppw.lib")
class CMouseHandler
{
public:
CMouseHandler(void);
~CMouseHandler(void);
static _bstr_t coordinatesToString(POINT point);
};
CMouseHandler.cpp
#include "CMouseHandler.h"
HHOOK mouseHook = NULL;
_bstr_t CMouseHandler::coordinatesToString(POINT point)
{
_bstr_t coordinates = "(";
_bstr_t xcoordinate = to_string((long double)point.x).c_str();
_bstr_t ycoordinate = to_string((long double)point.y).c_str();
coordinates += xcoordinate + "," + ycoordinate + ")";
return coordinates;
}
LRESULT CALLBACK MouseHookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
MSLLHOOKSTRUCT event = *((MSLLHOOKSTRUCT *)lParam);
if (nCode == HC_ACTION)
{
_bstr_t message = "Mouse action happened at position: ";
_bstr_t mouseCoordinates = CMouseHandler::coordinatesToString(event.pt);
message += mouseCoordinates;
}
return CallNextHookEx(mouseHook, nCode, wParam, lParam);
}
CMouseHandler::CMouseHandler()
{
mouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookCallback, NULL, 0);
while (GetMessage(NULL, NULL, 0, 0) != 0);
}
CMouseHandler::~CMouseHandler(void)
{
}
_bstr_t isn't defined, as visual studio doesn't recognise the type it assumes its an override specifier. You need to include comutil.h as specified in the documentation.

Show a list of applications like alt-tab in Win7

I am trying to print a list of running applications like alt-tab would give me. Here are what I have done so far:
1.In the beginning I tried EnumWindows, but I got hundreds of entries.
2.I found some similar questions and they led me to the blog of Raymond Chen.
http://blogs.msdn.com/b/oldnewthing/archive/2007/10/08/5351207.aspx
However it still shows more than 100 windows(window_num1 being 158 and window_num2 being 329), while alt-tab would give me only 4. What did I do wrong? Here is my code:
#include <windows.h>
#include <tchar.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "user32.lib")
HWND windowHandle;
int window_num1=0;
int window_num2=0;
BOOL IsAltTabWindow(HWND hwnd)
{
if (hwnd == GetShellWindow()) //Desktop
return false;
// Start at the root owner
HWND hwndWalk = GetAncestor(hwnd, GA_ROOTOWNER);
// See if we are the last active visible popup
HWND hwndTry;
while ((hwndTry = GetLastActivePopup(hwndWalk)) != hwndTry)
{
if (IsWindowVisible(hwndTry))
break;
hwndWalk = hwndTry;
}
return hwndWalk == hwnd;
}
BOOL CALLBACK MyEnumProc(HWND hWnd, LPARAM lParam)
{
TCHAR title[500];
ZeroMemory(title, sizeof(title));
//string strTitle;
GetWindowText(hWnd, title, sizeof(title)/sizeof(title[0]));
if (IsAltTabWindow(hWnd))
{
_tprintf(_T("Value is %s\n"), title);
window_num1++;
}
window_num2++;
//strTitle += title; // Convert to std::string
if(_tcsstr(title, _T("Excel")))
{
windowHandle = hWnd;
return FALSE;
}
return TRUE;
}
void MyFunc(void) //(called by main)
{
EnumWindows(MyEnumProc, 0);
}
int main()
{
MyFunc();
cout<<endl<<window_num1<<endl<<window_num2;
return 0;
}
You failure is, that you should walk only visible windows... read the blog again.
For each visible window, walk up its owner chain until you find
the root owner. Then walk back down the visible last active popup
chain until you find a visible window. If you're back to where you're
started, then put the window in the Alt+↹Tab list.
Your code walks over every window!
Just use IsWindowVisible
BOOL CALLBACK MyEnumProc(HWND hWnd, LPARAM lParam)
{
TCHAR title[256] = {0,};
if (IsWindowVisible(hWnd) && GetWindowTextLength(hWnd) > 0)
{
window_num1++;
GetWindowText(hWnd, title, _countof(title));
_tprintf(_T("Value is %d, %s\n"), window_num1, title);
}
return TRUE;
}

C++ using SetWindowsHookEx only works with strange vcl code added to it. in BCB2009

I have a strange situation using SetWindowsHookEx
I have a bcb 2009 project with a form and a Memo on it.
in the create we load the Dll and attach the function handler's to both sides.
The idea is that when the key board is hit a message appear in the memo box and when a mouse event happen an other text appears in the memo box.
The strange this is that when I cleaned the code from debug information it stops working. That means the hook got triggered one time and than it was over.
In the debug I was using some VCL TStringList to log key stokes data to disk. Playing with that code I finally detected that by adding
[code]
TList* lList = new TList();
delete lList;
To every one of the hook functions (keyboard, mouse) the code is working again.
What is wrong in my code that I have to do this?
This is the first time in 15 years I make a dll. so it can be something real basic in creating a dll or exporting the functions.
Every suggestion is welcome.
regards
JVDN
Some new additional information:
[solved]My target is win XP embedded. my application creates a error that closes the explorer by windows. And the hook is not working global in xp but only local. But it is working on my develop platform win 7 x64 global typing and mousing in notepad result in messages in the application.
[solution] Modified the WH_KEYBOARD to WH_KEYBOARD_LL and the mouse from WH_MOUSE to WH_MOUSE_LL solves the receiving key and mouse on Windows XP embedded.
Both the dll and the application have no runtime lib or packages.
DLL Code
[code]
//---------------------------------------------------------------------------
#include <vcl.h>
#include <windows.h>
#pragma hdrstop
//---------------------------------------------------------------------------
// Important note about DLL memory management when your DLL uses the
// static version of the RunTime Library:
//
// If your DLL exports any functions that pass String objects (or structs/
// classes containing nested Strings) as parameter or function results,
// you will need to add the library MEMMGR.LIB to both the DLL project and
// any other projects that use the DLL. You will also need to use MEMMGR.LIB
// if any other projects which use the DLL will be performing new or delete
// operations on any non-TObject-derived classes which are exported from the
// DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling
// EXE's to use the BORLNDMM.DLL as their memory manager. In these cases,
// the file BORLNDMM.DLL should be deployed along with your DLL.
//
// To avoid using BORLNDMM.DLL, pass string information using "char *" or
// ShortString parameters.
//
// If your DLL uses the dynamic version of the RTL, you do not need to
// explicitly add MEMMGR.LIB as this will be done implicitly for you
//---------------------------------------------------------------------------
typedef void __stdcall ( *typFn)(WPARAM,LPARAM);
static typFn gGUIProcessingKeyboard = NULL;
static HHOOK gGUIProcessingKeyboardHook = NULL;
static typFn gGUIProcessingMouse = NULL;;
static HHOOK gGUIProcessingMouseHook = NULL;
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}
//---------------------------------------------------------------------------
extern "C"
{ __declspec(dllexport) void SetGUIProcessingKeyboard(typFn aHandle);
__declspec(dllexport) void ReleaseGUIProcessingKeyboard(typFn aHandle);
__declspec(dllexport) LRESULT CALLBACK wireKeyboardProc(int code, WPARAM wParam,LPARAM lParam);
__declspec(dllexport) void SetKeyboardHookHandle(HHOOK aHook );
__declspec(dllexport) void SetGUIProcessingMouse(typFn aHandle);
__declspec(dllexport) void ReleaseGUIProcessingMouse(typFn aHandle);
__declspec(dllexport) void SetMouseHookHandle(HHOOK aHook );
__declspec(dllexport) LRESULT CALLBACK wireMouseProc(int code, WPARAM wParam,LPARAM lParam);
/**
* Set the keyboard loop back handle
*/
void SetGUIProcessingKeyboard(typFn aHandle)
{
if (aHandle != gGUIProcessingKeyboard)
{
gGUIProcessingKeyboard = aHandle;
}
}
/**
* Release the keyboard loop back handle
*/
void ReleaseGUIProcessingKeyboard(typFn aHandle)
{
gGUIProcessingKeyboard = NULL;
}
/**
* Set the handle used for tapping the Keyboard
*/
void SetKeyboardHookHandle(HHOOK aHook )
{
gGUIProcessingKeyboardHook = aHook;
}
/**
* Tapping the keyboard from the other applications
*/
LRESULT CALLBACK wireKeyboardProc(int code, WPARAM wParam,LPARAM lParam)
{
TList* lList = new TList();
delete lList;
if (code < 0) {
return CallNextHookEx(gGUIProcessingKeyboardHook, code, wParam, lParam);
}
if (NULL != gGUIProcessingKeyboard)
{
gGUIProcessingKeyboard( wParam,lParam);
}
return CallNextHookEx(gGUIProcessingKeyboardHook, code, wParam, lParam);
}
/**
* Set the mouse loop back handle
*/
void SetGUIProcessingMouse(typFn aHandle)
{
if (aHandle != gGUIProcessingMouse)
{
gGUIProcessingMouse = aHandle;
}
}
/**
* Release the mouse loop back handle
*/
void ReleaseGUIProcessingMouse(typFn aHandle)
{
gGUIProcessingMouse = NULL;
}
/**
* Set the handle used for tapping the mouse
*/
void SetMouseHookHandle(HHOOK aHook )
{
gGUIProcessingMouseHook = aHook;
}
/**
* Tapping the mouse from the other applications
*/
LRESULT CALLBACK wireMouseProc(int code, WPARAM wParam,LPARAM lParam)
{
TList* lList = new TList();
delete lList;
// if (gGUIProcessingMouseHook != NULL)
// {
if (code < 0) {
return CallNextHookEx(gGUIProcessingMouseHook, code, wParam, lParam);
}
if (NULL != gGUIProcessingMouse)
{
gGUIProcessingMouse( wParam,lParam);
}
return CallNextHookEx(gGUIProcessingMouseHook, code, wParam, lParam);
// }
// return 0;
}
} // extern C
And here is the application.
[code cpp]
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "MonitoringToolMain.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
typedef void __stdcall ( __closure *typFn)(WPARAM,LPARAM);
TForm1 *Form1;
HHOOK TForm1::mHook = NULL;
typedef void __stdcall (*typSetHook)(HHOOK);
typedef LRESULT CALLBACK ( *typHookFunc)(int,WPARAM,LPARAM);
static HHOOK gMyGUIProcessingKeyboardHook = NULL;
static HHOOK gMyGUIProcessingMouseHook = NULL;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
void __stdcall TForm1::MyKeyboardProc(
WPARAM wParam,
LPARAM lParam
)
{
if (Form1 != NULL)
{
Form1->Memo1->Lines->Add(L"GotA keyboard");
}
}
void __stdcall TForm1::MyMouseProc(
WPARAM wParam,
LPARAM lParam
)
{
if (Form1 != NULL)
{
Form1->Memo1->Lines->Add(L"Pip pip");
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
if (NULL == mHinst)
{
mHinst = LoadLibrary("KeyboardMouseHookDLL.dll");
}
if (mHinst)
{
typedef void (*Install)(typFn);
// the keyboard
typSetHook SetHook = (typSetHook) GetProcAddress( mHinst, "_SetKeyboardHookHandle" );
typHookFunc wireKeyboardProc = (typHookFunc)GetProcAddress(mHinst, "wireKeyboardProc" );
Install install = (Install) GetProcAddress(mHinst, "_SetGUIProcessingKeyboard");
if (install)
{
install(&MyKeyboardProc);
}
if ((NULL != wireKeyboardProc) &&
(NULL != SetHook) )
{
gMyGUIProcessingKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)wireKeyboardProc,mHinst,NULL);
SetHook(gMyGUIProcessingKeyboardHook);
}
// The mouse
typSetHook SetMouseHook = (typSetHook) GetProcAddress(mHinst, "_SetMouseHookHandle");
typHookFunc wireMouseProc = (typHookFunc)GetProcAddress(mHinst, "wireMouseProc");
Install installMouse = (Install) GetProcAddress(mHinst, "_SetGUIProcessingMouse");
if (installMouse)
{
installMouse(&MyMouseProc);
}
if ((NULL != wireMouseProc) &&
(NULL != SetMouseHook) )
{
gMyGUIProcessingMouseHook = SetWindowsHookEx(WH_MOUSE,(HOOKPROC)wireMouseProc,mHinst,NULL);
SetMouseHook(gMyGUIProcessingMouseHook);
}
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
if (NULL == mHinst)
{
mHinst = LoadLibrary("KeyboardMouseHookDLL.dll");
}
if (mHinst)
{
if (NULL != gMyGUIProcessingKeyboardHook )
{
UnhookWindowsHookEx(gMyGUIProcessingKeyboardHook);
gMyGUIProcessingKeyboardHook = NULL;
}
typedef void (*Uninstall)(typFn);
Uninstall uninstall = (Uninstall) GetProcAddress(mHinst, "_ReleaseGUIProcessingKeyboard");
if (uninstall)
{
uninstall(&MyKeyboardProc);
}
if (NULL != gMyGUIProcessingMouseHook )
{
UnhookWindowsHookEx(gMyGUIProcessingMouseHook);
gMyGUIProcessingMouseHook = NULL;
}
Uninstall uninstallMouse = (Uninstall) GetProcAddress(mHinst, "_ReleaseGUIProcessingMouse");
if (uninstallMouse)
{
uninstallMouse(&MyMouseProc);
}
FreeLibrary(mHinst);
mHinst = NULL;
}
}
//---------------------------------------------------------------------------
And the form header
[code]
//---------------------------------------------------------------------------
#ifndef MonitoringToolMainH
#define MonitoringToolMainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TMemo *Memo1;
void __fastcall FormCreate(TObject *Sender);
void __fastcall FormDestroy(TObject *Sender);
private: // User declarations
int __stdcall lKeyBoard();
void __stdcall MyKeyboardProc( WPARAM wParam, LPARAM lParam );
void __stdcall MyMouseProc( WPARAM wParam, LPARAM lParam );
HINSTANCE mHinst;
static HHOOK mHook;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
If you're installing a global system hook, the hook DLL will be injected in each running process. As each process has its own memory space, you'll need to define a shared data section to place variables like the hook handles, otherwise they will be different for each process.
#pragma data_seg(".SHARDAT")
static HHOOK gGUIProcessingKeyboardHook = NULL;
static HHOOK gGUIProcessingMouseHook = NULL;
#pragma data_seg()
Also don't register function pointers to the hook DLL, as you will ask other processes to call the registered functions in your application. It's better to register the HWND of your application and a window message.
Create a exported function in your DLL that sets the hook and stores HWND and custom message number, f.e.:
#pragma data_seg(".SHARDAT")
static HHOOK g_keybHook = NULL;
static HHOOK g_mouseHook = NULL;
HWND g_registeredWnd = NULL;
UINT g_registeredKeybMsg = 0;
UINT g_registeredMouseMsg = 0;
#pragma data_seg()
HINSTANCE g_hInstance = NULL;
BOOL InstallHook(HWND registeredWnd, UINT registeredKeybMsg, UINT registeredMouseMsg)
{
if (g_hHook != NULL) return FALSE; // Hook already installed
g_keybHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeybProc, g_hInstance, 0);
if (g_keybHook == NULL) return FALSE; // Failed to install hook
g_registeredWnd = registeredWnd;
g_registeredKeybMsg = registeredKeybMsg;
g_registeredMouseMsg = registeredMouseMsg;
return TRUE;
}
In the DllEntryPoint you save hinst in g_hInstance in case reason == DLL_PROCESS_ATTACH:
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
if ((reason == DLL_PROCESS_ATTACH) && (g_hInstance == NULL))
g_hInstance = hinst;
return 1;
}
In your application you register 2 window messages with the RegisterWindowMessage function and pass these values to the InstallHook function from the hook DLL. Then your application needs to handle those messages in its message loop.
registeredKeybMsg = RegisterWindowMessage("MyOwnKeybHookMsg");
registeredMouseMsg = RegisterWindowMessage("MyOwnMouseHookMsg");
InstallHook(hwnd, registeredKeybMsg, registeredMouseMsg);

WinAPI window doesn't appear

And I can't figure out why. My code:
#include <windows.h>
#include <commctrl.h>
#include <cstdio>
#include <stdarg.h>
#include <string>
#include <cmath>
#include <vector>
#include "resources.hpp"
using std::string;
using std::vector;
struct undostruct{
/* add later */};
char buffer[2048];
HWND statusbar;
HINSTANCE hinst;
vector<undostruct> undo;
void show_error(const char* format,...){
va_list args;
va_start(args,format);
vsprintf(buffer,format,args);
va_end(args);
MessageBox(NULL,buffer,"ERROR",MB_OK);}
HWND create_tooltip(HWND parent,char* tip,unsigned uid,unsigned extraflags=0){
HWND tt=CreateWindowEx(WS_EX_TOPMOST,TOOLTIPS_CLASS,NULL,WS_POPUP|TTS_NOPREFIX|TTS_ALWAYSTIP,0,0,0,0,parent,NULL,NULL,NULL);
SetWindowPos(tt,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
TOOLINFO ti;
ti.cbSize=sizeof(TOOLINFO);
ti.uFlags=TTF_SUBCLASS|extraflags;
ti.hwnd=parent;
ti.hinst=NULL;
ti.uId=uid;
ti.lpszText=tip;
GetClientRect(parent,&ti.rect);
SendMessage(tt,TTM_ADDTOOL,0,(LPARAM)(LPTOOLINFO)&ti);
return tt;}
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
class Font{
private:
HFONT hfont;
public:
Font(const char* fname){
hfont=CreateFont(0,0,0,0,FW_NORMAL,false,false,false,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,fname);}
~Font(){
DeleteObject(hfont);}
operator HFONT(){
return hfont;}}courier("Courier New");
bool get_filename(char* fname,int len,HWND hwnd,bool save){
OPENFILENAME ofn;
ZeroMemory(&ofn,sizeof(OPENFILENAME));
ofn.lStructSize=sizeof(OPENFILENAME);
ofn.hwndOwner=hwnd;
ofn.lpstrFilter="Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0\0";
ofn.lpstrFile=fname;
ofn.nMaxFile=len;
ofn.lpstrTitle="Text Editor";
ofn.Flags=OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
if(save){
return GetSaveFileName(&ofn);}
else{
return GetOpenFileName(&ofn);}}
int WINAPI WinMain(HINSTANCE hprev,HINSTANCE hInst,LPSTR cmdline,int cmdshow){
WNDCLASSEX wcex;
//HACCEL haccel=LoadAccelerators(hInst,MAKEINTRESOURCE(ACCELS));
HWND hwnd;
MSG msg;
hinst=hInst;
//Register the window
wcex.cbSize=sizeof(WNDCLASSEX);
wcex.style=CS_HREDRAW|CS_VREDRAW;
wcex.lpfnWndProc=WndProc;
wcex.cbClsExtra=0;
wcex.cbWndExtra=0;
wcex.hInstance=hinst;
wcex.hIcon=NULL;
wcex.hCursor=NULL;
wcex.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName=MAKEINTRESOURCE(MAINMENU);
wcex.lpszClassName="ImageEditor";
wcex.hIconSm=NULL;
if(!RegisterClassEx(&wcex)){
show_error("Error %i: Failed to register the window.",GetLastError());
return -1;}
//Create the window
hwnd=CreateWindow("ImageEditor","Image Editor",WS_VISIBLE|WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hinst,NULL);
if(!hwnd){
show_error("Error %i: Failed to create the window.",GetLastError());
return -2;}
//Show/Update the window
ShowWindow(hwnd,cmdshow);
UpdateWindow(hwnd);
//Initialize common controls
/*INITCOMMONCONTROLSEX iccex;
iccex.dwICC=ICC_WIN95_CLASSES;
iccex.dwSize=sizeof(INITCOMMONCONTROLSEX);
InitCommonControlsEx(&iccex);*/
//Go into the main program loop
while(GetMessage(&msg,NULL,0,0)){
//if(!TranslateAccelerator(hwnd,haccel,&msg)){
TranslateMessage(&msg);
DispatchMessage(&msg);}//}
return msg.wParam;}
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam){
static int sizes[]={260,330,420,520};
switch(msg){
case WM_CREATE:
statusbar=CreateWindow(STATUSCLASSNAME,"",WS_CHILD|WS_BORDER|WS_VISIBLE,-100,-100,10,10,hwnd,NULL,hinst,NULL);
if(!statusbar){
show_error("Error %i: Failed to create the statusbar.",GetLastError());}
//Description|Characters|Size|Lines|Line|Column
SendMessage(statusbar,SB_SETPARTS,sizeof(sizes),(LPARAM)sizes);
break;
case WM_QUIT:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_COMMAND:
//switch(LOWORD(wparam)){}
//break;
default:
return DefWindowProc(hwnd,msg,wparam,lparam);}
return 0;}
Also, my compiler doesn't recognize INITCOMMONCONTROLSEX when it should, which is commented out near the end of WinMain.
The most likely bug in this code is that you need to run InitCommonControls BEFORE creating a window. And forget that InitCommonControlsEx() code, you'll be better with a plain old InitCommonControls.
Remember to check every function's return value and use GetLastError().
Also, you're trying to reinvent the wheel and instead of rolling out your own window creating procedure I suggest you to take a look at how others do it, or even use WTL, it's not that difficult.