Examples

PowerBuilder Native Interface

Examples

The following code fragments are from a C++ program that opens a window. The window has a menu item that invokes the Open event of a PowerBuilder application.

Calling ProcessPBMessage

The call to ProcessPBMessage is in a loop in the WinMain function:

int __stdcall WinMain(HINSTANCE hInstance, 
                      HINSTANCE hPrevInstance,
                      LPSTR lpCmdLine,
                      int nCmdShow)
{
   MSG msg;

   WNDCLASSEX wcex;

// initialization code omitted
   ...
   RegisterClassEx(&wcex);

   HWND hWnd = CreateWindow(szWndClsName,
      "OpenPBWindow", WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL,
      hInstance, NULL);

   if (!hWnd)
   {
    return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   try
   {
       while (GetMessage(&msg, NULL, 0, 0))
       {
          TranslateMessage(&msg);
          DispatchMessage(&msg);

          // Call to ProcessPBMessage
          if (session)
             session->ProcessPBMessage();
      }
   }
   catch(...)
      {
          MessageBox(NULL, "Exception occurs",
            "Exception", MB_OK);
      }
   return msg.wParam;
}

Loading the PBVM and triggering an event

In the WndProc function, when the WM_CREATE message is passed, the PBVM is loaded and the library list, containing openwin.pbl, is passed to CreateSession. When the user selects the menu item that opens the PowerBuilder window, the FindGroup, FindClass, and GetMethodID functions obtain the information needed to create a new application object, initialize the PBCallInfo structure, and trigger the application object's Open event:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
   WPARAM wParam, LPARAM lParam)
{
  int wmId, wmEvent;
  PAINTSTRUCT ps;
  HDC hdc;

  switch (message)
  {
    case WM_CREATE:
      {
       // Load the PBVM
       hPBVMInst = ::LoadLibrary("pbvm125.dll");
       P_PB_GetVM getvm = (P_PB_GetVM)
           GetProcAddress(hPBVMInst,"PB_GetVM");
       IPB_VM* vm = NULL;
       getvm(&vm);

       // Define the library list and create the session
       static const char *liblist[] = {"openwin.pbl"};
       vm-> CreateSession("openwin", liblist, 1,
          &session);
       break;
      }

    case WM_COMMAND:
       wmId = LOWORD(wParam);
       wmEvent = HIWORD(wParam);
       // Parse the menu selections:
       switch (wmId)
       {
         case ID_PB_VISUAL:
         {
           // Initialize PBCallInfo and trigger the
           // application open event
           try
           {
               pbgroup group = session->FindGroup
                  ("openwin", pbgroup_application);
               pbclass cls = session->FindClass(group,
                   "openwin");
               pbmethodID mid = session->GetMethodID
                   (cls, "open", PBRT_EVENT, "QS");
               pbobject obj = session->NewObject(cls);

               PBCallInfo ci;
               session->InitCallInfo(cls, mid, &ci);
               session->TriggerEvent(obj, mid, &ci);
               session->FreeCallInfo(&ci);
           }
           catch(...)
           {
              MessageBox(NULL, "Exception occurs",
                 "Exception", MB_OK);
           }
          break;
         }
         default:
            return DefWindowProc(hWnd, message, wParam,
               lParam);
         }
         break;
      case WM_PAINT:
         hdc = BeginPaint(hWnd, &ps);
         RECT rt;
         GetClientRect(hWnd, &rt);
         EndPaint(hWnd, &ps);
         break;
      case WM_DESTROY:
         session->Release();
         session = NULL;
         FreeLibrary(hPBVMInst);
         PostQuitMessage(0);
         break;
      default:
         return DefWindowProc(hWnd, message, wParam,
            lParam);
   }
   return 0;
}

Testing ProcessPBMessage

You can test the ProcessPBMessage function with a simple PowerBuilder application like this one:

  1. Create a PowerBuilder application called openwin in openwin.pbl.

  2. Create a main window, w_main, with three buttons.

  3. Insert a window-level function, of_setcolor, that takes three integers as arguments and has this script:

    this.backcolor = rgb(red,green,blue)
  4. Insert a window-level user event, ue_test, with this script:

    MessageBox("ue_test", "This is a user event")
  5. Provide the following scripts for the clicked events of the buttons:

    //cb_1:
    MessageBox("Button 1", "Clicked")
    parent.of_setcolor(255, 255, 0)

    //cb_2:
    MessageBox("Button 2", "Clicked")
    parent.PostEvent("ue_event") // not fired
    parent.of_setcolor(255, 0, 0)

    //cb_3:
    MessageBox("Button 3", "Clicked")
    cb_1.PostEvent(Clicked!) // not fired
  6. Script the application's Open event:

    open (w_main)

When the ProcessPBMessage function is included in the C++ application, the application runs from C++ as it does in PowerBuilder. The posted events in cb_2 and cb_3 are processed.

Now try commenting out these lines in the C++ application, recompiling, and running the application again:

if (session)
session->ProcessPBMessage();

The message boxes still display (response windows have their own message loop) and the of_setcolor function is called, but the posted events do not fire.