API Question Does oapiRegisterWindow exist? [Yes, it exists and works perfectly!]

Bibi Uncle

50% Orbinaut, 50% Developer
Addon Developer
Joined
Aug 12, 2010
Messages
192
Reaction score
0
Points
0
Location
Québec, QC
Hi everyone!

My question can probably only be answered by Dr. Martin, but I'll make it public for everybody. Is the function oapiRegisterWindow, defined in the Orbiter API, really do something? It is not documented and I can't find any use of it in any samples. Also, searching for it in the forum only leads me to this jarmonik's thread, but does not help me very much.

I want to know if it exists. If it's the case, what are the available flags and what is its behavior?

I am trying to define an owned window as a custom plug-in for Orbiter. Using oapiOpenDialog isn't enough for me, since I am planning to use a rebar and a docking mechanism (Visual Studio style). I actually use Win32++, but this library is pretty straight-forward and open source, so I can modify anything to fit with Orbiter.

Thanks in advance ;)
 
Last edited:

martins

Orbiter Founder
Orbiter Founder
Joined
Mar 31, 2008
Messages
2,448
Reaction score
462
Points
83
Website
orbit.medphys.ucl.ac.uk
The function does exist, but the fact that it isn't document or used in any of the samples is a bit suspicious. It's probably not tested (much), so you will be its primary tester.

Here is what it is supposed to do:
oapiRegisterWindow(HINSTANCE hDLLInst, HWND hWnd, DWORD flag = 0)

Register window hWnd, defined in module hDLLInst, with Orbiter's window manager. Registering with the window manager is necessary so that the window will actually be displayed in fullscreen mode. (Not sure if hDLLInst is actually used. For dialogs, this is the place where Orbiter looks for the dialog template, but for normal windows this may well not be required).

The 'flag' parameter is the same as for oapiOpenDialogEx. Please note that from the next beta, most flags except for DLG_ALLOWMULTI will be deprecated, because Win7 doesn't allow to add title buttons in the same way as XP any more, so I've decided to ditch the custom title buttons. All window flags related to title buttons will be ignored.

For closing the window you should probably be able to use oapiCloseDialog(), since there isn't an oapiCloseWindow function. oapiCloseDialog isn't dialog-specific, it simply removes the window from the window manager's list.
 

Bibi Uncle

50% Orbinaut, 50% Developer
Addon Developer
Joined
Aug 12, 2010
Messages
192
Reaction score
0
Points
0
Location
Québec, QC
And for the messages, do I send them to oapiDefDialogProc?

I tested it with a WS_POPUP|WS_VISIBLE window, and it does not seem to work. THe window is displayed, but Orbiter stops refreshing. Even if I close the dialog, Orbiter remains freezed.

---------- Post added at 22:42 ---------- Previous post was at 19:58 ----------

After further testing in my late dev night, I confirm that your function actually works.

However, I can't make it work with Win32++. I think this is due to the new thread created. Orbiter seems to not be refreshed by the OS, every messages are sent to the new thread of my window.

I created an empty project with pure Win32 code, and it works like a charm. Here is a detailed code with lots of comments to help others in creating new windows. I experienced a lot with it, so you can have my different thoughts about it.

Everything between "big comments" (those with '=' signs) is very important. Copy it in Visual Studio for better tabulation of the comments.

Code:
#define ORBITER_MODULE
#define STRICT

#include "Orbitersdk.h"

// Global variables
int g_cmdID = NULL;
HINSTANCE g_hInstance = NULL;
HWND g_hWnd = NULL;
HWND g_hWndOrbiter = NULL;

// Global functions
void OpenWindow(void* context);
LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

DLLCLBK void InitModule(HINSTANCE hModule)
{
	g_hInstance = hModule;

	// Standard custom command registration.
	g_cmdID = oapiRegisterCustomCmd("Win32 Test", "Win32 Test", &OpenWindow, NULL);

	// Register the window class.
	WNDCLASS wndClass;
	wndClass.style         = CS_HREDRAW|CS_VREDRAW;
	wndClass.lpfnWndProc   = &WndProc;
	wndClass.cbClsExtra    = 0;
	wndClass.cbWndExtra    = 0;
	wndClass.hInstance     = hModule;
	wndClass.hIcon         = NULL;
	wndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
	wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndClass.lpszMenuName  = NULL;
	wndClass.lpszClassName = "Test Window"; // Don't forget to match this class name when you create the window!
	if(!RegisterClass (&wndClass))
		MessageBox(NULL, "Cannot register window.", "Error", MB_ICONERROR);
}

DLLCLBK void ExitModule(HINSTANCE hModule)
{
	// Just to clean everything when the user deselects your module.
	if(g_cmdID)
		oapiUnregisterCustomCmd(g_cmdID);
}

DLLCLBK void opcOpenRenderViewport(HWND hRenderWnd, DWORD width, DWORD height, BOOL fullscreen)
{
	// =====================================================
	// You'll need this pointer during the creation of the window
	// =====================================================
	g_hWndOrbiter = hRenderWnd;
}

DLLCLBK void opcCloseRenderViewport()
{
	// To faciliate debugging.
	g_hWndOrbiter = NULL;
}

void OpenWindow(void* context)
{
	// Create window
	g_hWnd = CreateWindowEx( 
    WS_EX_TOOLWINDOW,					// tool window extend style. Looks better with the other windows.
										// You can use WS_EX_OVERLAPPEDWINDOW which provides minimizing functionnality.
    "Test Window",						// class name
    "Test",								// window name
    WS_OVERLAPPEDWINDOW|WS_VISIBLE,		// visible overlapped window
    CW_USEDEFAULT,						// default horizontal position
    CW_USEDEFAULT,						// default vertical position
    CW_USEDEFAULT,						// default width
    CW_USEDEFAULT,						// default height
	// ======================================================================================
	// This is vital if you want your module to be available in fullscreen mode.
	// We specify the Orbiter window as the parent, but we do not specify WS_CHILD.
	// Therefore, Windows creates an owned window by Orbiter, and always keep it
	// above Orbiter in the z-order.
    (HWND) g_hWndOrbiter,				// Orbiter window as parent, to create a owned window
	//=======================================================================================
    (HMENU) NULL,						// No menu
    g_hInstance,						// DLL instance handle
	NULL);

	if(!g_hWnd)
	{
		MessageBox(NULL, "Cannot create window", "Error", MB_ICONERROR);
		return;
	}
	// ==============================
	// Register the window to Orbiter
	// ==============================
	if(!oapiRegisterWindow(g_hInstance, g_hWnd, NULL))
		MessageBox(NULL, "Cannot register window to Orbiter.", "Error", MB_ICONERROR);
}

LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch(uMsg)
	{
		// TODO: Add handled messages
		// Don't forget to return 1!
	}

	// ====================================================================
	// This function redraws Orbiter window when you move the child window.
	// Help reducing the "big white area".
	// Since this is not a dialog, you DO NOT RETURN ITS VALUE.
	// Actually, I'm pretty sure it always returns 0.
	// ====================================================================
	oapiDefDialogProc (hWnd, uMsg, wParam, lParam);

	// ==========================================================================
	// This function is vital. Without this line, your window creation will FAIL.
	// This is the returned value when you do not handle a message.
	// ==========================================================================
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
 
Top