Page 1 of 2

What parameters does PB use internally to create windows?

Posted: Thu Nov 16, 2006 8:57 pm
by halo
I am attempting to create a window with no titlebar icon in BlitzMax, like this. This is a window, not an actual messagebox dialog:
Image

Apparently it can be done in PureBasic with the following code:

Code: Select all

OpenWindow(0, 0, 0, 240, 100, "Modal frame", #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered | #PB_Window_Invisible)
SetWindowLong_(WindowID(0), #GWL_EXSTYLE, GetWindowLong_(WindowID(0), #GWL_EXSTYLE) | #WS_EX_DLGMODALFRAME)
HideWindow(0, 0)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
However, it doesn't work in BlitzMax:

Code: Select all

Extern "win32"
	Function SetWindowLong:Int(hwnd:Int,index:Int,value:Int)="SetWindowLongA@12"
	Function GetWindowLong:Int(hWnd:Int, index:Int)="GetWindowLongA@8"
EndExtern

Local w=400
Local h=300
Local win:TGadget=CreateWindow("Window",(Desktop().ClientWidth()-w)/2,(Desktop().ClientHeight()-h)/2,w,h,Null,WINDOW_HIDDEN+WINDOW_TITLEBAR)
Local hWnd:Int = QueryGadget(win,QUERY_HWND)

SetWindowLong hWnd,GWL_EXSTYLE,GetWindowLong(hwnd,GWL_EXSTYLE)+WS_EX_DLGMODALFRAME
SetWindowPos( hWnd, 0,0,0,0,0, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER )
ShowGadget win

While WaitEvent()<>EVENT_WINDOWCLOSE
Wend
The only difference I can think of is perhaps BlitzMax and PureBasic use different parameters when the window is initially created, which makes PureBasic windows modifiable into the desired style, while BlitzMax windows are not.

My question is what are the parameters PureBasic uses internally when creating a window with the API command CreateWindow() or CreateWindowEx()? Is there anything else that might make BlitzMax windows not work with this style, while PureBasic windows do?

Posted: Thu Nov 16, 2006 9:00 pm
by IndieP
What about using the Pop-up style?

Posted: Thu Nov 16, 2006 9:46 pm
by AND51
I don't really understand: Is it possible to create "Don't ask me this again"-windows with 1 command? Like MessageRequester() creates 1 whole window + buttons? :shock:

Please, can you give some more code?

Your first code just creates an empty window in my PB 4.01... :cry:

Posted: Thu Nov 16, 2006 10:24 pm
by halo
The point is to make a window with a full-size titlebar, "X" close button, but no icon on the top-left. This can be used for a custom messagebox, an options window, or whatever else you want. As demonstrated, it works perfectly in PureBasic, and I am trying to figure out why it doesn't work in BlitzMax.

Re: What parameters does PB use internally to create windows

Posted: Thu Nov 16, 2006 10:42 pm
by ricardo
halo wrote: However, it doesn't work in BlitzMax
Why don't ask on blitzmax forum? Sounds more logic to me.

Posted: Fri Nov 17, 2006 1:03 am
by halo
Why don't ask on blitzmax forum? Sounds more logic to me.
I am, but they don't have any idea why it doesn't work. I am guessing that PB windows have an owner-drawn caption, or have some setting they are created with that allows what I want, because it obviously isn't just a matter of window style settings.

I am trying to figure out what is it that PureBasic does that allows this appearance.

Posted: Fri Nov 17, 2006 1:55 am
by srod
I'd look more closely at your blitz code as the following api code works fine, i.e. no internal Purebasic windows commands are used.

Code: Select all

Procedure WindowCallback(Window, Message, wParam, lParam) 
  Select Message 
    Case #WM_CLOSE 
      If MessageBox_(Window, "You sure?", "EXIT", #MB_YESNO) = #IDYES 
        DestroyWindow_(Window) 
      Else 
        Result  = 0 
      EndIf 
    Case #WM_DESTROY 
      PostQuitMessage_(0) 
      Result  = 0 
    Default 
      Result  = DefWindowProc_(Window, Message, wParam, lParam) 
  EndSelect 
  ProcedureReturn Result 
EndProcedure 

#Style  = #WS_VISIBLE | #WS_SYSMENU 

WindowClass.s  = "myclass" 
wc.WNDCLASSEX 
wc\cbSize  = SizeOf(WNDCLASSEX) 
wc\lpfnWndProc  = @WindowCallback() 
wc\hCursor  = LoadCursor_(0, #IDC_ARROW) 
wc\hbrBackground  = #COLOR_WINDOW+1 
wc\lpszClassName  = @WindowClass 
RegisterClassEx_(@wc) 

hWndMain  = CreateWindowEx_(#WS_EX_DLGMODALFRAME	, WindowClass, "Test-Window", #Style, 10, 10, 200, 200, 0, 0, 0, 0) 

While GetMessage_(msg.MSG, #Null, 0, 0 ) 
  TranslateMessage_(msg) 
  DispatchMessage_(msg) 
Wend 

Posted: Fri Nov 17, 2006 6:18 am
by halo
Thank you! That was what I needed. I traced the BlitzMax window class back and found that it was actively loading the default exe icon. I commented that out and the setting took effect.

I searched for the answer to this for a long time. The PB forum is one of the best places to find people who know the Windows API. :D

Posted: Fri Nov 17, 2006 10:30 am
by srod
You're welcome.

Posted: Fri Nov 17, 2006 1:03 pm
by AND51
I don't know, if this belongs to the topic, but nevertheless, I'll ask you.

How can I create a MessageBox containing a checkbox "Don't show this again"? Like the image in the 1st post!

When I browsed the internet with Google, I just found a download-packet (many *.mainfest, *.c, *.h files...) which should make me able to create those Messageboxes. I mention the keyword "XMessageBox".

Please, can you help me? I don't want to create those windows on my own. :?

Posted: Fri Nov 17, 2006 5:40 pm
by halo
Well, this looks like they have done all the work for you already:
http://www.codeproject.com/dialog/xmessagebox.asp

Alternatively, it might be easier just to create a messagebox from a window, using the style I just showed you.

Posted: Fri Nov 17, 2006 7:34 pm
by AND51
I already found this link via Google.

Morover, I don't understand your 2nd sentence:: Which 'messagebox from a window' did you show my?

I compiled all your codes from this thread, but nothing happended... 1 of the code even just created a window with no content.

I have PB 4.01.

Posted: Fri Nov 17, 2006 11:24 pm
by Sparkie
I'll give it a go. Optimize, cleanup, and use as desired. :)

updated for PB6+ by Fred

Code: Select all

; ***************************************************** 
; Code    : MessageRequester with "Don't ask me again" 
; Author  : Sparkie 
; Date    : November 17, 2006 
; OS      : Windows only 
; License : It's all yours to use as you so desire 
;           (props/credit are welcome) 
; ***************************************************** 

Global hHook = 0, oldProc = 0, askagain = 0 

;...This one is still missing in PB def 
#BS_TEXT = 0 

;...Make sure Checkbox ID <> any of the other MessageRequester buttons 
#CheckBoxID = 12 

;...Subclassed MessageRequester Procedure() 
Procedure MsgBoxProc(hwnd, msg, wParam, lParam) 
  result = CallWindowProc_(oldProc, hwnd, msg, wParam, lParam) 
  Select msg 
    Case #WM_DESTROY 
      ;...Get handle to our checkbox 
      hCheckBox = GetDlgItem_(hwnd, #CheckBoxID) 
      ;...Get the checkbox state. <0 = not checked> <1 = checked> 
      ;...For this test I'll set a Global var to = CheckBox state 
      ;...In a real app you could set the value in a config/ini file 
      ;...or maybe a use a Registry setting 
      askagain = SendMessage_(hCheckBox, #BM_GETCHECK, 0, 0) 
  EndSelect 
  ProcedureReturn result 
EndProcedure 

;...Our hook Procedure() 
Procedure CBTProc(nCode, wParam, lParam) 
  result = CallNextHookEx_(hHook, nCode,wParam,lParam) 
  ;...Creation of MessageRequester is here 
  If nCode = #HCBT_CREATEWND 
    *cbt_cw.CBT_CREATEWND = lParam 
    *lpcs.CREATESTRUCT = *cbt_cw\lpcs 
    ;...Take action only if this is our MessageRequester 
    If *lpcs\hWndParent = WindowID(0) And *lpcs\lpszClass = 32770 
      ;...Resize the MessageRequester to make room for our CheckBoxGadget 
      *lpcs\cy + 30 
    EndIf 
    result = 0 
  EndIf 
  
  ;...MessageRequester is about to become active 
  ;...Here we will add our "Don't ask me this again" checkbox 
  If nCode = #HCBT_ACTIVATE 
    hMsgBox = wParam 
    
    ;...Subclass the MessageRequester 
    oldProc = SetWindowLong_(hMsgBox, #GWL_WNDPROC, @MsgBoxProc()) 
    hCheckBox = CreateWindowEx_(0, "Button", "Don't ask me this again.", #BS_AUTOCHECKBOX | #BS_TEXT | #WS_GROUP | #WS_TABSTOP | #WS_CHILD | #WS_VISIBLE, 10, 95, 150, 25, hMsgBox, #CheckBoxID, GetModuleHandle_(0), 0) 
    hFont = GetStockObject_(#DEFAULT_GUI_FONT) 
    SendMessage_(hCheckBox, #WM_SETFONT, hFont, 0) 
    ;...Release the hook 
    If hHook 
      UnhookWindowsHookEx_(hHook) 
      hHook = 0 
    EndIf 
    result = 0 
  EndIf 
  ProcedureReturn result 
EndProcedure 
If OpenWindow(0, 100, 100, 300, 200, "Don't ask me again", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0)) 
  ButtonGadget(1, 10, 40, 280, 22, "Display Custom MessageRequester") 
  TextGadget(2, 10, 80, 280, 25, "") 
  Repeat 
    Event = WaitWindowEvent() 
    If Event = #PB_Event_Gadget And EventGadget() = 1 
      ;...Create a local hook to watch for MessageRequester 
      If askagain = 0 
        hHook = SetWindowsHookEx_(#WH_CBT, @CBTProc(), 0, GetCurrentThreadId_()) 
        MessageRequester("Welcome", "Do you want to continue?", #MB_YESNO | #MB_ICONQUESTION) 
      Else 
        MessageRequester("Sorry", "You requested not to see that message again.", #MB_OK | #MB_ICONINFORMATION) 
      EndIf 
      Select askagain 
        Case 0 
          SetGadgetText(2, "Ask me again was not checked") 
        Case 1 
          SetGadgetText(2, "Ask me again was checked") 
      EndSelect 
    EndIf 
  Until Event = #PB_Event_CloseWindow 
EndIf 
;...Just in case it's still there 
If hHook 
  UnhookWindowsHookEx_(hHook) 
  hHook = 0 
EndIf 
End

Posted: Fri Nov 17, 2006 11:40 pm
by netmaestro
Fabulous piece of code, Sparkie, and very instructive. You really are a coding guru, thanks for posting!

Posted: Sat Nov 18, 2006 12:33 am
by AND51
Thank you! I will have a closer look later. :D

WindowHook? Does this take effect on all MessageBoxes I open? I aask, because in my program I want some MessageBoxes with checkbox and some without checkboxes.