File: main.cpp
Size: 5877
Date: Mon, 07 Apr 2008 21:29:41 +0200
Type: cpp
//****************************************************************************
#pragma warning(disable : 4786)
 
#include <windows.h>
#include <pbext.h>
#include <richedit.h>
#include <commctrl.h>
#include <math.h>
 
#include <string>
using std::string;
 
HMODULE g_dll_hModule = 0;
 
PBXEXPORT LPCTSTR PBXCALL PBX_GetDescription()
{
    static const TCHAR desc[] = {
        "class u_canvas from userobject\n"
        "event int onpaint(ulong hdc)\n"
        "end class\n" 
    };
 
  return desc;
}
 
class CVisualExt : public IPBX_VisualObject
{
    static TCHAR s_className[];
 
    IPB_Session* d_session;
    pbobject    d_pbobj;
    HWND        d_hwnd;
    string      d_text;
    bool        d_buffer;
 
public:
    static HDC          memdc;
 
    CVisualExt(IPB_Session* session, pbobject pbobj)
        : 
        d_session(session), 
        d_pbobj(pbobj), 
        d_hwnd(NULL),
        d_text("Visual Extension")
    {
 
    }
 
    ~CVisualExt()
    {
    }
 
    LPCTSTR GetWindowClassName();
 
    HWND 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
    );
 
    PBXRESULT Invoke
        (
        IPB_Session *session, 
        pbobject    obj, 
        pbmethodID  mid,
        PBCallInfo  *ci
        );
 
    void Destroy()
    {
        delete this;
        DestroyWindow(d_hwnd);
    }
 
    HDC GetMemDC()
    {
        return memdc;
    }
 
    void TriggerEvent(LPCTSTR eventName);
 
    static void RegisterClass();
    static void UnregisterClass();
 
    static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 
};
 
TCHAR CVisualExt::s_className[] = "PBVisualExt";
HDC CVisualExt::memdc = 0;
 
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;
}
 
PBXRESULT CVisualExt::Invoke
    (
    IPB_Session *session, 
    pbobject    obj, 
    pbmethodID  mid,
    PBCallInfo  *ci
    )
{
    //switch(mid)
    //{
    //case 1:
    //  return PBX_FAIL;
    //default:
    //  return PBX_FAIL;
    //}
 
    return PBX_OK;
}
 
void CVisualExt::TriggerEvent(LPCTSTR eventName)
{
    pbclass clz = d_session->GetClass(d_pbobj);
    pbmethodID mid = d_session->GetMethodID(clz, eventName, PBRT_EVENT, "");
    pbulong lpb = (pbulong)memdc;
 
    PBCallInfo ci;
    d_session->InitCallInfo(clz, mid, &ci);
 
    pbint cnt = ci.pArgs->GetCount();
 
    ci.pArgs->GetAt(0)->SetUlong(lpb);
 
    d_session->TriggerEvent(d_pbobj, mid, &ci);
    d_session->FreeCallInfo(&ci);
 
    //ci.returnValue->SetInt(0);
}
 
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);
}
 
void CVisualExt::UnregisterClass()
{
    ::UnregisterClass(s_className, g_dll_hModule);
}
 
LRESULT CALLBACK CVisualExt::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    CVisualExt* ext = (CVisualExt*)::GetWindowLong(hwnd, GWL_USERDATA);
 
    switch(uMsg)
    {
        case WM_CREATE:
            return 0;
 
        case WM_SIZE:
            return 0;
 
        case WM_COMMAND:
            return 0;
 
        case WM_ERASEBKGND:
            return 1;
 
        case WM_PAINT:
            {
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint(hwnd, &ps);
 
                RECT rc;
                GetClientRect(hwnd, &rc);
 
                HDC lmemdc = CreateCompatibleDC(hdc);
                HBITMAP hmembmp = CreateCompatibleBitmap(hdc, rc.right - rc.left, rc.bottom - rc.top);
                HBITMAP oldbmp = (HBITMAP)SelectObject(lmemdc, hmembmp);
 
                memdc = lmemdc;
 
                ext->TriggerEvent("onpaint");
 
                BitBlt(hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, lmemdc, 0, 0, SRCCOPY);
 
                SelectObject(lmemdc, oldbmp);
                DeleteObject(hmembmp);
                DeleteDC(lmemdc);
                EndPaint(hwnd, &ps);
                return 0;
            }
    }
 
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
 
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("u_canvas") == 0)
    {
        *obj = new CVisualExt(pbsession, pbobj);
    }
    else
    {
        *obj = NULL;
        result = PBX_FAIL;
    }
 
    return PBX_OK;
};
 
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;
}