When the window or other visual control in which a visual native class resides is created in a PowerBuilder application, the PBVM calls the PBX_CreateVisualObject method in the extension automatically—the PowerBuilder application developer does not need to write a CREATE statement in a script. The PBVM also calls the IPBX_VisualObject’s CreateControl method. Every extension that contains visual native classes must export PBX_CreateVisualObject and implement CreateControl.
The following is sample code for PBX_CreateVisualObject:
PBXEXPORT PBXRESULT PBXCALL PBX_CreateVisualObject
(
IPB_Session* pbsession,
pbobject pbobj,
LPCTSTR className,
IPBX_VisualObject **obj
)
{
PBXRESULT result = PBX_OK;
string cn(className);
if (cn.compare("visualext") == 0)
{
*obj = new CVisualExt(pbsession, pbobj);
}
else
{
*obj = NULL;
result = PBX_FAIL;
}
return PBX_OK;
};
Before CreateControl can be called, the window class must be registered. This code uses the Windows RegisterClass method to register the window class with the class name s_className:
void CVisualExt::RegisterClass()
{
WNDCLASS wndclass;
wndclass.style = CS_GLOBALCLASS | CS_DBLCLKS;
wndclass.lpfnWndProc = WindowProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = g_dll_hModule;
wndclass.hIcon = NULL;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground =(HBRUSH) (COLOR_WINDOW + 1);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = s_className;
::RegisterClass (&wndclass);
}
You must also implement the Windows UnregisterClass method to unregister the class when the window is closed:
void CVisualExt::UnregisterClass()
{
::UnregisterClass(s_className, g_dll_hModule);
}
The RegisterClass and UnregisterClass methods are called in the initialization code for the PBX. This is the Visual C++ DllMain method:
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD reasonForCall,
LPVOID lpReserved
)
{
g_dll_hModule = (HMODULE)hModule;
switch (reasonForCall)
{
case DLL_PROCESS_ATTACH:
CVisualExt::RegisterClass();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
CVisualExt::UnregisterClass();
break;
}
return TRUE;
}
Every visual native class must implement the IPBX_VisualObject CreateControl method. After getting the class name with the IPBX_VisualObject GetClassName method, CreateControl passes the class name to the Windows CreateWindowEx method to create the window, then returns the window handle to the PBVM:
TCHAR CVisualExt::s_className[] = "PBVisualExt";
LPCTSTR CVisualExt::GetWindowClassName()
{
return s_className;
}
HWND CVisualExt::CreateControl
(
DWORD dwExStyle, // extended window style
LPCTSTR lpWindowName, // window name
DWORD dwStyle, // window style
int x, // horizontal position of window
int y, // vertical position of window
int nWidth, // window width
int nHeight, // window height
HWND hWndParent, // handle to parent or
// owner window
HINSTANCE hInstance // handle to application
// instance
)
{
d_hwnd = CreateWindowEx(dwExStyle, s_className,
lpWindowName, dwStyle, x, y, nWidth, nHeight,
hWndParent, NULL, hInstance, NULL);
::SetWindowLong(d_hwnd, GWL_USERDATA, (LONG)this);
return d_hwnd;
}