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:
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?
Please, can you give some more code?
Your first code just creates an empty window in my PB 4.01...

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.

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.
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.