Jump to content
The simFlight Network Forums

Recommended Posts

Posted

Hi all (especially Pete!)

I am having a little problem with coding my module Dialog app. I think I have it set up OK, but I am having some hassle setting up the timer with the SetTimer function.

Basically, my code is:

.....
// Handles
WNDPROC oldWndProc; // The standard window procedure used by the flight simulator
HWND hFSimWindow; // Flight simulator main window handle

HWND hwndDlg = NULL;// Handle for My dialog window
HINSTANCE g_hInst; // Handle for the mainDLL call

#define	MENU_ENTRY	"VSM Modules"
#define	ID_MY_MENUITEM1	40001

// My Dialog Routine
BOOL CALLBACK FSBDlgProc(HWND hwndDlg, UINT Message, WPARAM wParam, LPARAM lParam) 
{	

// Set the timer
SetTimer(
         hwndDlg, // handle to FSBridge
         IDT_TIMER1,            // timer identifier 

         20,                 // 1/1000th seconds: 10000 = 10 second interval 
         (TIMERPROC) NULL);     // no timer callback

	switch(Message)
		{
		case WM_INITDIALOG:
			{
                                //Initialise FSUIPC etc
				return 0;
			}

		case WM_TIMER:
			{
                          // Main Code - Get Sim Values using FSUIPC
                          // Display data to Static Text in the Dialog box
			return 0;
			}

		case WM_COMMAND:
			switch(LOWORD(wParam))
			{
				case IDC_CANCEL:
					PostMessage(hwndDlg, WM_CLOSE, 0, 0);
				break;

				case ID_FILE_EXIT:
                    PostMessage(hwndDlg, WM_CLOSE, 0, 0);
				break;
			}
		break;

		case WM_CLOSE:
			{
                DestroyWindow(hwndDlg);
			}
		break;

		case WM_DESTROY:
			{
                FSUIPC_Close();
		hwndDlg = NULL;
		KillTimer(hwndDlg, IDT_TIMER1);
			}
		break;

		default:
			return FALSE;
	}

	return TRUE;
}

/**
 * Main window procedure that is called by the flight simulator to process
 * incoming window messages.
 */
LRESULT CALLBACK FSimWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg) {
		case WM_NCPAINT:
			{
				HMENU hMenu, hMyMenu;
				hMenu = GetMenu(hwnd); //Copy the handle of the Menu item

				if (hMenu != NULL) {
					int i;
					// Look for our menu entry in the main menu.
					for (i = 0; i < GetMenuItemCount(hMenu); i++) {
						char buf[128];
						GetMenuString(hMenu, i, buf, 128, MF_BYPOSITION);
						if (strcmp(buf, MENU_ENTRY) == 0) {
							// It is already here, we do not need to add it again
							break;
						}
					} // end of loop

					if (i < GetMenuItemCount(hMenu)) {
						// It is already here, we do not need to add it again
						break;
					}

					/* Create new menu. NOTE: It seems that this will be
					 * reached more times, so we cannot save the handle, because
					 * in such case it could be destroyed and we will not have
					 * any access to it in the simulator.
					 */
					hMyMenu = CreateMenu();
					AppendMenu(hMyMenu, MF_STRING | MF_ENABLED, ID_MY_MENUITEM1, "&FSBridge");
					// add the created menu to the main menu
					AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT_PTR)hMyMenu, MENU_ENTRY);
				}
			}
			break;

		case WM_PAINT:
			{

			}
            break;

		case WM_COMMAND:
			switch (LOWORD(wParam))
			{
                case ID_MY_MENUITEM1:
					{
						// Only create Dialog if not existing
						if (!IsWindow(hwndDlg)) {

							hwndDlg = CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_FSBRIDGE),
								hwnd, FSBDlgProc);
							ShowWindow(hwndDlg, SW_SHOW);
						}
					}
					break;
			}
			//break;


			return TRUE;
	}

	// Call the original window procedure to handle all other messages
	return CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam);
}

/**
 * Entry point of the DLL.
 */
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
	g_hInst = hInstDLL; //copies the hInstDLL into "instance" for use it into all the APIs
	switch (fdwReason) {
		case DLL_PROCESS_ATTACH:
			// Finds the window of title "FS98MAIN" (FS) and returns the handle
			hFSimWindow = FindWindow("FS98MAIN", NULL);
			// Gets the handle of the standard FS proceedure
			oldWndProc = (WNDPROC)SetWindowLong(hFSimWindow, GWL_WNDPROC, (LONG)FSimWindowProc);

			break;
	}
	return TRUE;
}

Where do I place the SetTimer call? If I place it at the start of FSimWindowProc, FS stops painting the window. If I place where shown at the start of the Dialog procedure, it gets reset when any message gets sent to the Dialog procedure.

A better place seems to be in the WM_PAINT section of the main FSimWindowProc - any better suggestions?

Overall, is this the most efficient way of displaying dynamic FSUIPC generated text in an internal FS Dialog module at about the same frequency as the FS Framerate (about 20-40fps)?

Also, if I close the Dialog box, it will not reopen/re-initialise. Any ideas why? I presume it is OK to de-initialise using the Dialog procedure (WM_CLOSE) and not FSAPI module_deinit?

I am also having some runtime / stack issues around the transfering of data from the FSUIPC_PROCESS calls, but I will get to that next...

Apologies about the hefty post, but any helpful hints would be hugely appreciated.

Cheers,

Scott.

Posted

Where do I place the SetTimer call? If I place it at the start of FSimWindowProc, FS stops painting the window. If I place where shown at the start of the Dialog procedure, it gets reset when any message gets sent to the Dialog procedure.

The most obvious place in in the INIDIALOG call in the dialogue procedure, surely. That's when the dialogue window handle is first valid and it is called just the once, when the dialogue is created.

Overall, is this the most efficient way of displaying dynamic FSUIPC generated text in an internal FS Dialog module at about the same frequency as the FS Framerate (about 20-40fps)?

Well, not as efficient as a genuine FS gauge, of ocurse, which is using all of the ready built-in graphics stuff in FS and is getting called when its variables change no matter what the frame rate.

Also, if I close the Dialog box, it will not reopen/re-initialise. Any ideas why? I presume it is OK to de-initialise using the Dialog procedure (WM_CLOSE) and not FSAPI module_deinit?

If you are closing the FSUIPC link in the dialog, you should be opening it there too (in the INITDIALOG). If you open the FSUIPC link upon Module_Init, then close it in Module-Deinit. Symmetry is wonderful, isn't it? ;-).

Bearing in mind that all the FSUIPC_Open2 and FSUIPC_Close are doing is providing and removing (respectively) a fixed address of an area in which you will pass requests, I would have thought the simplest thing would be to do it on Init and Deinit.

Regards,

Pete

Posted

Thanks once again Pete, that worked a treat!

I am having issues read the Altitude from 0x0570 (also TAS from 0x02B8)

My relevant code is


DWORD dwSize = 2048;
BYTE pMem [2048];

if (FSUIPC_Open2(SIM_ANY, &dwResult, pMem, dwSize)) {
etc...

In a different module:

int ReadInitFS(double *FS_LatLong, float *FS_MainStates)
{	
DWORD dwResult;

	__int64 FS_LatLongTemp[3] = {0};
	__int32 FS_MainStatesTemp[4] = {0};

	// Get location & State
	//FSUIPC_Read(0x0560, 8, &FS_LatLongTemp[1], &dwResult);//Lat
	//FSUIPC_Read(0x0568, 8, &FS_LatLongTemp[2], &dwResult);//Long
	FSUIPC_Read(0x0570, 8, &FS_LatLongTemp[3], &dwResult);//Alt
	//FSUIPC_Read(0x057C, 4, &FS_MainStatesTemp[1], &dwResult);//Phi
	//FSUIPC_Read(0x0578, 4, &FS_MainStatesTemp[2], &dwResult);//Theta
	//FSUIPC_Read(0x0580, 4, &FS_MainStatesTemp[3], &dwResult);//Psi
	//FSUIPC_Read(0x02B8, 4, &FS_MainStatesTemp[4], &dwResult);//TAS
	FSUIPC_Process(&dwResult); // Process the request(s)

	// Change FS to Real Units: Lat Long Alt
	FS_LatLong[1] = (double)FS_LatLongTemp[1] * (90.0 / (10017500.0 * 65536.0 * 65536.0 ));
	FS_LatLong[2] = (double)FS_LatLongTemp[2] * (360.0 / (65536.0 * 65536.0 * 65536.0 * 65536.0));
	FS_LatLong[3] = (double)FS_LatLongTemp[3] / (65536.0 * 65536.0);

	// Phi, Theta, Psi
	FS_MainStates[1] = (float)FS_MainStatesTemp[1] * 360.0 / (65536.0 * 65536.0);
	FS_MainStates[2] = (float)FS_MainStatesTemp[2] * 360.0 / (65536.0 * 65536.0);
	FS_MainStates[3] = (float)FS_MainStatesTemp[3] * 360.0 / (65536.0 * 65536.0);
	FS_MainStates[4] = (float)FS_MainStatesTemp[4] / 128.0 / (float) MPS2KTS;

	return dwResult;
}

I can read Latitude, Longitude and the Euler angles perfectly.

As soon as I try reading Altitude or TAS, I get run-time stack errors about dwResult and FS_LatLongTemp / FS_MainStatesTemp.

I checked out FSInterogate, but it didn't tell me how Altitude differs from Lat/Long.

I also tried pulling Altitude and TAS out of the integer matrices and the run-time error dissappeared, but I am getting a value which changes with bank angle!

I wold very much appreciate any help!

Posted
__int64 FS_LatLongTemp[3] = {0};

__int32 FS_MainStatesTemp[4] = {0};

...

FSUIPC_Read(0x0570, 8, &FS_LatLongTemp[3], &dwResult);//Alt

...

As soon as I try reading Altitude or TAS, I get run-time stack errors about dwResult and FS_LatLongTemp / FS_MainStatesTemp.

I'm not surprised. You defined FS_LatLongTemp as having 3 elements, then try to read the Alt into the 4th one!

This is an elementary programming error -- in C/C++ array elements are numbered from 0, not 1. Once you get used to the language you'll never make this mistake again! ;-)

Regards

Pete

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use. Guidelines Privacy Policy We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.