yucad3d

CadWin host-owned-window mode

The second integration mode: the HOST owns the window and message loop, forwards each message to CadWin*, and yucad renders offscreen OpenGL into the window's DC. Drag pans, the wheel zooms — on the same document as the main window.

// CadWin host-owned-window mode: a SECOND plain Win32 window whose messages
// are forwarded to CadWin* — yucad renders offscreen GL into the host DC.
// Viewer + navigation (drag = pan, wheel = zoom) on the SAME document.
static LRESULT CALLBACK feat_win_proc(HWND w, UINT m, WPARAM wp, LPARAM lp) {
    const int x = (int)(short)LOWORD(lp), y = (int)(short)HIWORD(lp);
    switch (m) {
    case WM_CREATE:      CadWinCreate(g_hDwg, w);  return 0;
    case WM_DESTROY:     CadWinDestroy(g_hDwg, w); return 0;
    case WM_SIZE:        CadWinSize(g_hDwg, w, (int)wp, LOWORD(lp), HIWORD(lp)); return 0;
    case WM_PAINT:       { PAINTSTRUCT ps; BeginPaint(w, &ps); EndPaint(w, &ps);
                           CadWinPaint(g_hDwg, w); return 0; }
    case WM_LBUTTONDOWN: SetCapture(w); CadWinLButtonDown(g_hDwg, w, (int)wp, x, y); return 0;
    case WM_LBUTTONUP:   ReleaseCapture(); CadWinLButtonUp(g_hDwg, w, (int)wp, x, y); return 0;
    case WM_MBUTTONDOWN: SetCapture(w); CadWinMButtonDown(g_hDwg, w, (int)wp, x, y); return 0;
    case WM_MBUTTONUP:   ReleaseCapture(); CadWinMButtonUp(g_hDwg, w, (int)wp, x, y); return 0;
    case WM_MOUSEMOVE:   CadWinMouseMove(g_hDwg, w, (int)wp, x, y); return 0;
    case WM_MOUSEWHEEL:  { POINT p{ x, y }; ScreenToClient(w, &p);
                           CadWinMouseWheel(g_hDwg, w, GET_KEYSTATE_WPARAM(wp),
                                            GET_WHEEL_DELTA_WPARAM(wp), p.x, p.y); return 0; }
    case WM_HSCROLL:     CadWinHScroll(g_hDwg, w, LOWORD(wp), HIWORD(wp)); return 0;
    case WM_VSCROLL:     CadWinVScroll(g_hDwg, w, LOWORD(wp), HIWORD(wp)); return 0;
    }
    return DefWindowProcW(w, m, wp, lp);
}

static void feat_winmode() {
    static bool reg = false;
    if (!reg) {
        WNDCLASSW wc{}; wc.lpfnWndProc = feat_win_proc;
        wc.hInstance = GetModuleHandleW(nullptr);
        wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
        wc.lpszClassName = L"YuCadWinModeDemo";
        RegisterClassW(&wc); reg = true;
    }
    HWND w = CreateWindowExW(0, L"YuCadWinModeDemo",
        L"CadWin mode — host-owned window (drag = pan, wheel = zoom)",
        WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
        CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, g_main, nullptr,
        GetModuleHandleW(nullptr), nullptr);
    ShowWindow(w, SW_SHOW);
    set_status(L"CadWinCreate: second window renders the SAME document via the host-owned-window mode");
}
procedure TfrmMain.FeatWinPaint(Sender: TObject);
begin
  CadWinPaint(FhDwg, (Sender as TForm).Handle);
end;

procedure TfrmMain.FeatWinResize(Sender: TObject);
var f: TForm;
begin
  f := Sender as TForm;
  if f.HandleAllocated then
  begin
    CadWinSize(FhDwg, f.Handle, 0, f.ClientWidth, f.ClientHeight);
    f.Invalidate;
  end;
end;

procedure TfrmMain.FeatWinClose(Sender: TObject; var Action: TCloseAction);
begin
  CadWinDestroy(FhDwg, (Sender as TForm).Handle);
  Action := caFree;
end;

procedure TfrmMain.FeatWinMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if Button = mbLeft   then CadWinLButtonDown(FhDwg, (Sender as TForm).Handle, 0, X, Y);
  if Button = mbMiddle then CadWinMButtonDown(FhDwg, (Sender as TForm).Handle, 0, X, Y);
end;

procedure TfrmMain.FeatWinMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if Button = mbLeft   then CadWinLButtonUp(FhDwg, (Sender as TForm).Handle, 0, X, Y);
  if Button = mbMiddle then CadWinMButtonUp(FhDwg, (Sender as TForm).Handle, 0, X, Y);
end;

procedure TfrmMain.FeatWinMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  CadWinMouseMove(FhDwg, (Sender as TForm).Handle, 0, X, Y);
end;

procedure TfrmMain.FeatWinMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
var f: TForm; p: TPoint;
begin
  f := Sender as TForm;
  p := f.ScreenToClient(MousePos);
  CadWinMouseWheel(FhDwg, f.Handle, 0, WheelDelta, p.X, p.Y);
  Handled := True;
end;

    14:                                           // CadWin host-window mode
      begin
        frm := TForm.Create(Self);
        frm.Caption      := 'CadWin mode - host-owned window (drag = pan, wheel = zoom)';
        frm.ClientWidth  := 800;
        frm.ClientHeight := 600;
        frm.Position     := poDefault;
        frm.OnPaint      := FeatWinPaint;
        frm.OnResize     := FeatWinResize;
        frm.OnClose      := FeatWinClose;
        frm.OnMouseDown  := FeatWinMouseDown;
        frm.OnMouseUp    := FeatWinMouseUp;
        frm.OnMouseMove  := FeatWinMouseMove;
        frm.OnMouseWheel := FeatWinMouseWheel;
        frm.Show;
        CadWinCreate(FhDwg, frm.Handle);
        CadWinSize(FhDwg, frm.Handle, 0, frm.ClientWidth, frm.ClientHeight);
        frm.Invalidate;
        StatusBar.SimpleText := 'CadWinCreate: second window renders the SAME document via the host-owned-window mode';
      end;
    // CadWin host-owned-window mode: a SECOND plain window whose messages are
    // forwarded to CadWin* — yucad renders offscreen GL into this form's DC.
    // Viewer + navigation (drag = pan, wheel = zoom) on the SAME document.
    private sealed class CadWinForm : Form
    {
        private readonly int _dwg;
        public CadWinForm(int dwg)
        {
            _dwg = dwg;
            Text = "CadWin mode — host-owned window (drag = pan, wheel = zoom)";
            ClientSize = new Size(800, 600);
            SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
        }
        protected override void OnHandleCreated(EventArgs e)   { base.OnHandleCreated(e); YuCadApi.CadWinCreate(_dwg, Handle);
                                                                 YuCadApi.CadWinSize(_dwg, Handle, 0, ClientSize.Width, ClientSize.Height); }
        protected override void OnHandleDestroyed(EventArgs e) { YuCadApi.CadWinDestroy(_dwg, Handle); base.OnHandleDestroyed(e); }
        protected override void OnResize(EventArgs e)          { base.OnResize(e); if (IsHandleCreated) { YuCadApi.CadWinSize(_dwg, Handle, 0, ClientSize.Width, ClientSize.Height); Invalidate(); } }
        protected override void OnPaint(PaintEventArgs e)      { YuCadApi.CadWinPaint(_dwg, Handle); }
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (e.Button == MouseButtons.Left)   YuCadApi.CadWinLButtonDown(_dwg, Handle, 0, e.X, e.Y);
            if (e.Button == MouseButtons.Middle) YuCadApi.CadWinMButtonDown(_dwg, Handle, 0, e.X, e.Y);
        }
        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            if (e.Button == MouseButtons.Left)   YuCadApi.CadWinLButtonUp(_dwg, Handle, 0, e.X, e.Y);
            if (e.Button == MouseButtons.Middle) YuCadApi.CadWinMButtonUp(_dwg, Handle, 0, e.X, e.Y);
        }
        protected override void OnMouseMove(MouseEventArgs e)  { base.OnMouseMove(e); YuCadApi.CadWinMouseMove(_dwg, Handle, 0, e.X, e.Y); }
        protected override void OnMouseWheel(MouseEventArgs e) { base.OnMouseWheel(e); YuCadApi.CadWinMouseWheel(_dwg, Handle, 0, e.Delta, e.X, e.Y); }
    }

    private void FeatWinMode()
    {
        new CadWinForm(_hDwg).Show(this);
        SetStatus("CadWinCreate: second window renders the SAME document via the host-owned-window mode");
    }
This code is extracted verbatim from the shipped demo hosts (examples/cpp, examples/delphi, examples/csharp) — run the matching menu item there to see it live.