Okay, here ya go:
(You DO get event feedback, in case you are wondering.)
If you don't need 3D, or only need simple 3D you can do with OpenGL, I would definitely choose BlitzPlus over this method.

PureBasic DLL source:
(You DO get event feedback, in case you are wondering.)
If you don't need 3D, or only need simple 3D you can do with OpenGL, I would definitely choose BlitzPlus over this method.

PureBasic DLL source:
hook.l oldProc.l mainHWnd.l Global *MainHWnd Global svar.s Structure message hWnd.l messagename.l wParam.l lParam.l EndStructure Structure msgque *next.msgque *previous.msgque hWnd.l message.l wParam.l lParam.l EndStructure DefType.msgque *que Declare WinProc(hWnd,Mesg,wParam,lParam) Declare AddMessage(messname,hWnd,wParam,lParam) ;General ;============================================================= ;Procedure KeyboardHookProc(code,wParam,*lParam.MSG) ;If *lParam\message=#WM_KEYDOWN ; TranslateMessage_(*lParam.MSG) ; DispatchMessage_(*lParam.MSG) ; EndIf ;EndProcedure Procedure SubclassProc(hWnd,Mesg,wParam,lParam) Shared oldProc,MainHWnd Select Mesg Case #wm_command mess=1 Case #wm_close SetWindowLong_(MainHWnd,#GWL_WNDPROC,oldProc) Case #WM_SIZE rect.rect GetWindowRect_(hWND,rect) w=rect\right-rect\left h=rect\bottom-rect\top If w<MINWINDOWWIDTH resize=1 w=MINWINDOWWIDTH EndIf If h<MINWINDOWHEIGHT resize=1 h=MINWINDOWHEIGHT EndIf If resize=1 MoveWindow_(hWND,rect\left,rect\top,w,h,1) EndIf ; UpdateStatusBar(0) EndSelect AddMessage(mess,hWnd,wParam,lParam) ProcedureReturn CallWindowProc_(oldProc,hWnd,Mesg,wParam,lParam) EndProcedure ProcedureDLL InitWindow(*hWND) Shared MainHWnd,oldProc oldProc=SetWindowLong_(*hWnd,#GWL_WNDPROC,@SubclassProc()) NewList filo.msgque() MainHWnd=*hWnd EndProcedure Procedure WinProc(hWnd,Mesg,wParam,lParam) Shared hook Select Mesg Case #wm_command mess=1 Case #wm_close UnhookWindowsHookEx_(hook) ;DestroyWindow_(hWnd); don't do this in the DLL. mess=2 EndSelect AddMessage(mess,hWnd,wParam,lParam) ProcedureReturn DefWindowProc_(hWnd,Mesg,wParam,lParam) EndProcedure ProcedureDLL.l pbCheckStatus(*a.message) Shared *que *que=LastElement(filo()) If *que<>0 *a\hWnd=*que\hWnd *a\messagename=*que\message *a\wParam=*que\wParam *a\lParam=*que\lParam DeleteElement(filo()) Else *a\hWnd=0 *a\messagename=0 *a\wParam=0 *a\lParam=0 EndIf ProcedureReturn *a\messagename EndProcedure Procedure AddMessage(messname,hWnd,wParam,lParam) Shared *que If messname>0 ResetList(filo()) *que=AddElement(filo()) If *que<>0 *que\hWnd=hWnd *que\message=messname *que\wParam=wParam *que\lParam=lParam EndIf EndIf EndProcedure ;============================================================= ;Window ProcedureDLL.l pbOpenWindow(num,x,y,InnerWidth,InnerHeight,Flags,Title$,ParentWindowID) ProcedureReturn pbOpenWindow(num,x,y,InnerWidth,InnerHeight,Flags,Title$,ParentWindowID) EndProcedure Procedure pbUseWindow(windowid) UseWindow(windowid) EndProcedure ;============================================================= ;Toolbar ProcedureDLL.l pbCreateToolBar(num,*hWND) ProcedureReturn CreateToolBar(num,*hWND) EndProcedure ProcedureDLL.l pbToolBarSeparator() ProcedureReturn ToolBarSeparator() EndProcedure ProcedureDLL.l pbToolBarStandardButton(num,icon) ProcedureReturn ToolBarStandardButton(num,icon) EndProcedure ProcedureDLL.l pbToolBarImageButton(num,icon) ProcedureReturn ToolBarImageButton(num,icon) EndProcedure ProcedureDLL pbAddTBTextButton(num,text$,flags) pbAddTBtextButton(num,text$,flags) EndProcedure ProcedureDLL pbToolBarToolTip(buttonid,text$) ToolBarToolTip(buttonid,text$) EndProcedure ;============================================================= ;Statusbar ProcedureDLL.l pbCreateStatusBar(num,*hWND) ProcedureReturn CreateStatusBar(num,*hWND) EndProcedure ProcedureDLL.l pbAddStatusBarField(width) ProcedureReturn AddStatusBarField(width) EndProcedure ProcedureDLL pbStatusBarText(text$,field) ProcedureReturn StatusBarText(0,field,text$) EndProcedure ;============================================================= ;Menu ProcedureDLL.l pbCreateMenu(num,*hWnd) ProcedureReturn CreateMenu(num,*hWnd) EndProcedure ProcedureDLL pbMenuTitle(text$) ProcedureReturn MenuTitle(text$) EndProcedure ProcedureDLL.l pbMenuBar() ProcedureReturn MenuBar() EndProcedure ProcedureDLL.l pbMenuItem(num,text$) ProcedureReturn MenuItem(num,text$) EndProcedure ProcedureDLL pbOpenSubMenu(text$) ProcedureReturn OpenSubMenu(text$) EndProcedure ProcedureDLL pbCloseSubMenu() ProcedureReturn CloseSubMenu() EndProcedure ProcedureDLL pbDisplayPopupMenu(num,hWnd) DisplayPopupMenu(num,hWnd) EndProcedure ProcedureDLL pbSetMenuItemState(menu,item,state) ProcedureReturn SetMenuItemState(menu,item,state) EndProcedure ProcedureDLL.l pbGetMenuItemState(menu,item) ProcedureReturn GetMenuItemState(menu,item) EndProcedure ProcedureDLL.l pbMenuHeight() ProcedureReturn MenuHeight() EndProcedure ;============================================================= ;Toolbar Pro ;ProcedureDLL.l pbCreateTB(num,*hWnd,w,h,Flags) ;ProcedureReturn CreateTB(num,*hWnd,w,h) ;EndProcedure ;ProcedureDLL.l pbAddTBbutton(num,image,flags) ;ProcedureReturn AddTBbutton(num,image,$2) ;EndProcedure ;ProcedureDLL pbUpdateTB(tbid) ;UpdateTB(tbid) ;EndProcedure ;============================================================= ;Requesters ProcedureDLL.l pbMessageRequester(Title$,Text$,Flags) ProcedureReturn MessageRequester(Title$,Text$,Flags) EndProcedure ProcedureDLL.l pbSaveFileRequester(Title$,DefaultFile$,Pattern$,PatternPosition) svar.s=SaveFileRequester(Title$,DefaultFile$,Pattern$,PatternPosition) ProcedureReturn @svar.s EndProcedure ProcedureDLL.l pbOpenFileRequester(Title$,DefaultFile$,Pattern$,PatternPosition) svar.s=OpenFileRequester(Title$,DefaultFile$,Pattern$,PatternPosition) ProcedureReturn @svar.s EndProcedure ProcedureDLL.l pbSelectedFilePattern() ProcedureReturn SelectedFilePattern() EndProcedure ;============================================================= ;Image ProcedureDLL.l pbLoadImage(num,file$) ProcedureReturn LoadImage(num,file$) EndProcedure ProcedureDLL.l pbUseImage(num) ProcedureReturn UseImage(num) EndProcedure ProcedureDLL.l pbFreeImage(num) ProcedureReturn FreeImage(num) EndProcedure ;============================================================= ;Gadget ProcedureDLL.l pbCreateGadgetList(*hWnd) ProcedureReturn CreateGadgetList(*hWnd) EndProcedure ProcedureDLL pbUseGadgetList(*hWND) UseGadgetList(*hWND) EndProcedure ProcedureDLL.l pbCloseGadgetList() ProcedureReturn CloseGadgetList() EndProcedure ProcedureDLL pbResizeGadget(num,x,y,Width,Height) ResizeGadget(num,x,y,Width,Height) EndProcedure ProcedureDLL.l pbListIconGadget(num,x,y,Width,Height,Title$,TitleWidth,Flags) ProcedureReturn ListIconGadget(num,x,y,Width,Height,Title$,TitleWidth,Flags) EndProcedure ProcedureDLL pbAddGadgetItem(gadgetid,position,text$,imageid) If imageid=-1 ProcedureReturn AddGadgetItem(gadgetid,position,text$) Else ProcedureReturn AddGadgetItem(gadgetid,position,text$,imageid) EndIf EndProcedure ProcedureDLL.l pbGetGadgetState(gadgetid) ProcedureReturn GetGadgetState(gadgetid) EndProcedure ProcedureDLL.l pbComboBoxGadget(num,x,y,Width,Height,Flags) ProcedureReturn ComboBoxGadget(num,x,y,Width,Height,Flags) EndProcedure ProcedureDLL pbSetGadgetState(gadgetid,state) SetGadgetState(gadgetid,state) EndProcedure ProcedureDLL pbRemoveGadgetItem(gadgetid,item) RemoveGadgetItem(gadgetid,item) EndProcedure ProcedureDLL.l pbGetGadgetItemState(gadgetid,item) ProcedureReturn GetGadgetItemState(gadgetid,item) EndProcedure ProcedureDLL pbSetGadgetItemState(gadgetid,item,state) SetGadgetItemState(gadgetid,item,state) EndProcedure ProcedureDLL pbClearGadgetItemList(gadgetid) ClearGadgetItemList(gadgetid) EndProcedure ;============================================================= ;Tree Gadget ProcedureDLL.l pbTreeGadget(num,x,y,width,height,flags) ProcedureReturn TreeGadget(num,x,y,width,height,flags) EndProcedure ProcedureDLL.l pbOpenTreeGadgetNode(gadgetid,position) If position=-1 OpenTreeGadgetNode(gadgetid) Else OpenTreeGadgetNode(gadgetid,position) EndIf EndProcedure ProcedureDLL.l pbCloseTreeGadgetNode(gadgetid,position) If position=-1 CloseTreeGadgetNode(gadgetid) Else CloseTreeGadgetNode(gadgetid,position) EndIf EndProcedure ProcedureDLL pbGadgetID(num) EndProcedure ProcedureDLL pbPanelGadget(num,x,y,w,h) ProcedureReturn PanelGadget(num,x,y,w,h) EndProcedure ProcedureDLL.l pbContainerGadget(gadgetid,x,y,width,height,flags) ProcedureReturn ContainerGadget(gadgetid,x,y,width,height,flags) EndProcedure ProcedureDLL.l pbFreeGadget(gadgetid) ProcedureReturn FreeGadget(gadgetid) EndProcedure ProcedureDLL.l pbButtonImageGadget(num,x,y,w,h,image) ProcedureReturn ButtonImageGadget(num,x,y,w,h,image) EndProcedure ProcedureDLL.l pbButtonGadget(num,x,y,w,h,title$,style) ProcedureReturn ButtonGadget(num,x,y,w,h,title$,style) EndProcedure ProcedureDLL.l pbTextGadget(num,x,y,Width,Height,Text$,Flags) ProcedureReturn TextGadget(num,x,y,Width,Height,Text$,Flags) EndProcedure ProcedureDLL.l pbStringGadget(num,x,y,w,h,content$,style) ProcedureReturn StringGadget(num,x,y,w,h,content$,style) EndProcedure ProcedureDLL.l pbGetGadgetText(num,bank) svar.s=GetGadgetText(num) ProcedureReturn @svar EndProcedure