Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
How To Create or Call Crystal Reports inside Foxpro?
Message
From
16/07/2002 02:11:38
Walter Meester
HoogkarspelNetherlands
 
 
To
15/07/2002 14:53:32
General information
Forum:
Visual FoxPro
Category:
Reports & Report designer
Miscellaneous
Thread ID:
00630954
Message ID:
00678969
Views:
41
Hi Paul,

The keystrokes and the mousewheel is captured by the ActiveX control and never passed throug to VFP. This is a common problem with ActiveX controls. Since the ActiveX CrViewer is used to display a report and users want VFP to react on keystrokes like CTRL + P (for printing) or ESC (for closing the form), etc, this is a real pain.

I've written a DLL to capture the messages from the activeX internally and determine if they should be send to VFP.

All keystrokes besides the arrows (which are used to navigate trhough the report) are send to VFP. The mousewheel message is send to VFP if the cursor is not over the activeX control

O.K. here is the C sourcecode . Compiled in VC++ 6.0
#include <PRO_EXT.H>
#include <mmsystem.h>
#include <winuser.h>

#define MAXHOOKS 100

long oldwindowproc[MAXHOOKS] ;
long newwindowhwnd[MAXHOOKS] ;
long windowshandle[MAXHOOKS] ;
int hookno = 0;

LRESULT CALLBACK HandleWindowMessage(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) ;
/*
void InitHook (ParamBlk *parm) ;
void DestroyHook() ;
*/

void InitHook (ParamBlk *parm)
{
	HWND hSource ;
	HWND hDest ;
	int i = 1;
	int j = 0;
	int f = 0;

	// _BreakPoint(); 

	hSource = (HWND) parm->p[0].val.ev_long ;
	hDest   = (HWND) parm->p[1].val.ev_long ;

	for (i=1; newwindowhwnd[i] != -1  && i <= hookno ; i++) ; 
	
	if (i <= MAXHOOKS){

		for (j=1; windowshandle[j] != (long)hSource && j <= hookno ; j++) ; // Check if already exists
		
		if (windowshandle[j] != (long)hSource) // if not then hook it
		{
			if (i > hookno){
				hookno++ ;
			} ;

			newwindowhwnd[i] = (long)hDest ;
			windowshandle[i] = (long)hSource ;
			oldwindowproc[i] = GetWindowLong(hSource,GWL_WNDPROC);
			SetWindowLong(hSource, GWL_WNDPROC, (LONG)HandleWindowMessage);
		} ;
	} ;
}


LRESULT CALLBACK HandleWindowMessage(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	LRESULT retvalue = 0 ;
    RECT rect;
    POINT pt;
	int i ;

	for (i=1; windowshandle[i] != (long)hwndDlg && i < hookno ; i++) ;

	if (windowshandle[i] == (long)hwndDlg) {

		switch (uMsg){
		case WM_CHAR:
		case WM_KEYUP:
		case WM_KEYDOWN:
		case WM_SYSKEYUP:
		case WM_SYSKEYDOWN:
		case WM_SYSCHAR:


			if (wParam != VK_UP && wParam != VK_DOWN && wParam != VK_LEFT && wParam != VK_RIGHT){ 
				SendNotifyMessage((HWND)newwindowhwnd[i],uMsg, wParam, lParam) ;
				if (wParam == VK_RETURN && uMsg == WM_KEYDOWN) {
					/* Pass it through VFP */
					SendNotifyMessage((HWND)newwindowhwnd[i],WM_CHAR, wParam, lParam) ;
				};


				break ;
			} 

		case 0x020A: /* Mousewheel, check if the cursor is positioned over the captured window */
		    GetClientRect(hwndDlg,&rect);
		    MapWindowPoints(hwndDlg,NULL,(LPPOINT)&rect,2);
			GetCursorPos(&pt);
			if (!PtInRect(&rect,pt) || (WindowFromPoint(pt) != hwndDlg)) {
				/* Pass it through VFP */
				SendNotifyMessage((HWND)newwindowhwnd[i],uMsg, wParam, lParam) ;
				break ;
			};

		default:
			/* Pass it through the activeX control */
			return (CallWindowProc((WNDPROC)oldwindowproc[i], hwndDlg, uMsg, wParam, lParam)) ;
		}
	} ;
	return (0) ;
}

void DestroyHook()
{
	int i = 1 ;
	for (i=1; i <= hookno; i++){
		SetWindowLong((HWND)windowshandle[i], GWL_WNDPROC, oldwindowproc[i]);
	} ;
}

void ResetHooks(ParamBlk *parm)
{
	int i;
	long j = 0;
	long nHwnd=parm->p[0].val.ev_long ;

	for (i=1; i <= hookno ; i++){
		if (newwindowhwnd[i] == nHwnd){

			SetWindowLong((HWND)windowshandle[i], GWL_WNDPROC, oldwindowproc[i]);
			newwindowhwnd[i] = -1 ;
			windowshandle[i] = -1 ;
			oldwindowproc[i] = -1 ;
			j++ ;
		}
	}
	_RetInt(j,10) ;
}


FoxInfo myFoxInfo[] = {
	{"INITHOOK", (FPFI) InitHook, 2, "II"},
    {"RESETHOOKS",(FPFI) ResetHooks, 1, "I"},
 	{"DESTROYHOOK", (FPFI) DestroyHook, CALLONUNLOAD, ""}
};

extern "C" {
 FoxTable _FoxTable = {
    (FoxTable *)0, sizeof(myFoxInfo) / sizeof(FoxInfo), myFoxInfo
 };
}
O.K. fine, now what ?

Well to connect this code to VFP, we have to pass the WHND of the windows who capture the keystrokes when the activeX control is active. The ActiveX control actually contains a layered number of windows of which only two actually capture the messages. You can check this with a tool like SPY++

In the case for crystal 8.5 the names of the internal windows are: SysTreeView32 for the group tree and ReportView for the actual report.

In the INIT of the form containing the activeX control:
SET LIBRARY TO keybhook.dll ADDITIVE
the following code is activated by a timer (only once). I forgot why...
IF THISFORM.hWndDocument = 0
	THISFORM.gethwnd
ENDIF
The GetHWND method:
DECLARE INTEGER FindWindowEx IN User32.dll INTEGER, INTEGER, STRING, INTEGER
nHwnd=FindWindowEx(THISFORM.HWnd,0,0,0)
nHwnd=FindWindowEx(nHWnd,0,"ReportAlbum"+CHR(0),0)
nHwnd=FindWindowEx(nHWnd,0,"ViewHolder"+CHR(0),0)

THISFORM.hWndCrTreeView=FindWindowEx(nHWnd,0,"SysTreeView32"+CHR(0),0)
THISFORM.hWndDocument=FindWindowEx(nHWnd,0,"ReportView"+CHR(0),0)

inithook(THISFORM.hWndDocument,THISFORM.hwnd)
inithook(THISFORM.hWndCrTreeView,THISFORM.hwnd)
In the qeuryunload:
=RESETHOOKS(THISFORM.HWnd)
One problem remains however:
Since I did not made a mechanism to capture drilldown windows yet, the solution works perfectly for the main window, but for all drilldown tabs the solution does not work yet.

HTH,

I'll send you a compiled keybhook.dll by mail.

Walter,



>Hello Walter,
>
>I am having some of the Crystal Reports problems that you mentioned. Specifically, I am having problems with the keystrokes being captured by the RDC. You mentioned that you wrote a C dll to solve this problem. Would you be willing to give me the dll or at least explain how you did it? Any help would be appreciated.
>
>Thanks,
>Paul Ezerski
>and
>Jane Harper
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform