Creating visual class instances
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;
};
Registering the window class
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;
}
Implementing CreateControl
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;
}