
FreeBASIC's Official Forums
|
| View previous topic :: View next topic |
| Author |
Message |
|
|
Posted: Apr 08, 2006 18:38 Post subject: Gooey gooey gooey |
|
|
Okay, I posted a barebones GUI library awhile back, but because of limitations I completely canned it and started over. Well, I just hit a point where I finally surpassed the first project yesterday, so I figured I oughta post a demo:
http://www.betterwebber.com/stuff/jinx/jinx_test.exe
http://www.betterwebber.com/stuff/jinx/jinx_test.bas
The library's really more of an object framework than a GUI library... But it works such that I can write GTK drivers later and just compile a different set of driver modules. Plus, the modules are completely separate from the code so users can write extensions without recompiling the library. So the nice things:
- It's a static library, no runtime DLLs.
- Only includes what modules you use, so you can write 50k GUI apps
- Can/will be cross platform in the future
- Extendable
- Simple. No jxGet_Top_Bar_Color_Around_X_Button() functions, just jxGet and jxSet
BUT, it's still a mess:
- Event system is a federal disaster area
- Memory leaks galore (yeah, be careful running the demo in Win98)
- Slow development (I'm a senior engineering student, no time)
So I'm probably going to need some help, as much as I hate the thought of working with other people. First, is I'd like to redo the layouts. I was hoping to making something like "BorderLayout" in Java (the one thing they do get right), where or HTML, where someone could just plop elements in instead of having to provide coordinates (that was a major PITA making that demo). Any suggestions? (ballpark's open on this one)
So: help wanted, the more the merrier, but I really have no experience working in an online project with more than 3 people (that documentation thing was a disaster), so if anyone here has experience working in any big OSS settings, I could use some advice.
And finally, I have some questions about WinAPI in general:
- My buttons seem sluggish, and I can't fix it. What gives?
- Is there a way to get themed controls without making some chump use manifests. I can't use owner-drawn controls, that would make my library as bloated as wx-c.
- Anyone know how to get TAB focusin' working?
So, there you have it. Last time I posted something like this, a bunch of people got excited and started posting technical questions about things I hadn't done yet, so lemme be clear: This is nowhere near completion, all that's in that demo is all that's implemented, and anything's open. |
| |
|
| Back to top |
|
 |
|
|
Posted: Apr 09, 2006 1:54 Post subject: |
|
|
Hey Jofers,
the test proggie ran ok on my machine, win XP, but crashes(not responding) if I press a button without and value typed in the text boxes.
I also get a memory error when I click the close box, but the program closes anyway.
The code looks GREAT. I would use this lib for sure. KISS :-) (Keep It Simple Stupid) is an awesome programming philosophy.
Unfortunately this is not my area of expertise, otherwise I would lend a mind to the project. |
| |
|
| Back to top |
|
 |
|
|
Posted: Apr 09, 2006 2:09 Post subject: |
|
|
Tabbing behavior in windows is controlled by the message loop using the IsDialogMessage() function. (Tabbing is automatic in a dialog box.)
By sending messages to the dialog message handler, you loose some keys which the system handles automatically, so it’s a compromise. If you want the best of both, then you might have to write your own key handling.
The response of the buttons looked fine in the sample you posted. Perhaps the response problem does not show in such tiny program? Are you using the windows message queue, or checking messages in a loop?
I never bothered with manifests, so I don’t know how they work.
Garvan |
| |
|
| Back to top |
|
 |
|
|
Posted: Apr 09, 2006 4:35 Post subject: |
|
|
It's... just so simple! I think this is the first time in my life I've been able to simply read the source of a GUI-based program, and actually understand what effect it has.
With your layout question, I'd be inclined towards the Java-based layout containers. It's flexible and predictable in output. HTML documents use what's known as a box model, which means things flow from top to bottom, with inline/box/floating elements, which works well for documents, but not so much for GUIs.
Test program crashes if there's nothing in the input box. :| |
| |
|
| Back to top |
|
 |
|
|
Posted: Apr 09, 2006 7:03 Post subject: |
|
|
Yeah, the button crash just shows how uncoordinated I am about this, problem fixed :)
Anyway, I'm trying to get rid of all the memory errors & leaks, thanks for the feedback.
Sisophon2001: I tried sticking IsDialogMessage() into my main message loop for windows... nothin'. This is the code I'm usin' for that portion:
| Code:
|
|
Do While GetMessage(@WndMsg, NULL, NULL, NULL) <> False Result = IsDialogMessage(Obj_Data->hWnd, @WndMsg) If Result = 0 Then TranslateMessage @WndMsg DispatchMessage @WndMsg End If Loop |
I'm using regular ol' CreateWindowEx for my windows, no dialog boxes. Do I just have to handle the tab key myself (I wish I didn't!) |
| |
|
| Back to top |
|
 |
|
|
Posted: Apr 09, 2006 8:06 Post subject: |
|
|
A working example follows. There may be other factors like default flags that I am not aware of that stops it working for you.
You don’t need to capture and handle tabs, you need to insert code to handle all key presses, even those swallowed up by the dialog handler. I may not be much of an issue, but if it becomes one later, I will look up the code to handle the key translation, and translate it to FB. I was one of the topics covered in a book I have, but I did not have to use the code myself.
Garvan
| Code:
|
|
Option Explicit
#include once "windows.bi" Dim Shared ghInstance As HINSTANCE
Declare Function FB_Button (Text As String, Byval hWnd As HWND , Byval id As Integer, _ Byval X As Integer, Byval Y As Integer, Byval W As Integer, Byval H As Integer) As HWND
Declare Function WinMain ( Byval hInstance As HINSTANCE, _ Byval hPrevInstance As HINSTANCE, _ Byval szCmdLine As String, _ Byval iCmdShow As Integer ) As Integer End WinMain( GetModuleHandle( null ), null, Command( ), SW_NORMAL )
''::::: Function WndProc ( Byval hWnd As HWND, _ Byval wMsg As UINT, _ Byval wParam As WPARAM, _ Byval lParam As LPARAM ) As LRESULT Function = 0 Select Case( wMsg ) Case WM_CREATE Exit Function
Case WM_PAINT Dim rct As RECT Dim pnt As PAINTSTRUCT Dim hDC As HDC hDC = BeginPaint( hWnd, @pnt ) GetClientRect( hWnd, @rct ) DrawText( hDC, _ "Hello, World!", _ -1, _ @rct, _ DT_SINGLELINE Or DT_CENTER Or DT_VCENTER ) EndPaint( hWnd, @pnt ) Exit Function Case WM_KEYDOWN If( lobyte( wParam ) = 27 ) Then PostMessage( hWnd, WM_CLOSE, 0, 0 ) End If
Case WM_DESTROY PostQuitMessage( 0 ) Exit Function End Select Function = DefWindowProc( hWnd, wMsg, wParam, lParam ) End Function
''::::: Function WinMain ( Byval hInstance As HINSTANCE, _ Byval hPrevInstance As HINSTANCE, _ Byval szCmdLine As String, _ Byval iCmdShow As Integer ) As Integer Dim wMsg As MSG Dim wcls As WNDCLASS Dim hWnd As HWND ghInstance = hInstance Function = 0 With wcls .style = CS_HREDRAW Or CS_VREDRAW .lpfnWndProc = @WndProc .cbClsExtra = 0 .cbWndExtra = 0 .hInstance = hInstance .hIcon = LoadIcon( NULL, IDI_APPLICATION ) .hCursor = LoadCursor( NULL, IDC_ARROW ) .hbrBackground = GetStockObject( WHITE_BRUSH ) .lpszMenuName = NULL .lpszClassName = @"HelloWin" End With If( RegisterClass( @wcls ) = FALSE ) Then MessageBox( null, "Failed to register wcls", "Error", MB_ICONERROR ) Exit Function End If hWnd = CreateWindowEx( 0, _ @"HelloWin", _ "The Hello Program", _ WS_OVERLAPPEDWINDOW, _ CW_USEDEFAULT, _ CW_USEDEFAULT, _ CW_USEDEFAULT, _ CW_USEDEFAULT, _ NULL, _ NULL, _ hInstance, _ NULL ) FB_Button("Button 1", hWnd, 123, 10, 10, 100, 40) FB_Button("Button 2", hWnd, 234, 10, 70, 100, 40)
ShowWindow( hWnd, iCmdShow ) UpdateWindow( hWnd ) While( GetMessage( @wMsg, NULL, 0, 0 ) <> FALSE ) If IsDialogMessage(hWnd, @wMsg) = 0 Then TranslateMessage( @wMsg ) DispatchMessage( @wMsg ) End If Wend Function = wMsg.wParam
End Function
Function FB_Button (Text As String, Byval hWnd As HWND , Byval id As Integer, _ Byval X As Integer, Byval Y As Integer, Byval W As Integer, Byval H As Integer) As HWND
Dim As Integer style, Exstyle Dim As HWND A
Style = WS_CHILD Or WS_VISIBLE Or BS_MULTILINE Or BS_PUSHBUTTON Or WS_TABSTOP Exstyle = WS_EX_STATICEDGE
A = CreateWindowEx(Exstyle,"button",Text,Style,X, Y, W, H, hWnd, id, ghInstance, 0) Return A End Function |
EDIT: Perhaps WS_TABSTOP ? |
| |
|
| Back to top |
|
 |
|
|
Posted: Apr 09, 2006 15:22 Post subject: |
|
|
This uses WS_TABSTOP, WS_GROUP WS_EX_CONTROLPARENT and IsDialogMessage() [thanks Garvan!]
| Code:
|
|
Option Explicit
#define WIN_INCLUDEALL #include once "windows.bi" #include once "win/commctrl.bi"
Declare Function WndProc ( Byval hWnd As HWND, _ Byval wMsg As UINT, _ Byval wParam As WPARAM, _ Byval lParam As LPARAM ) As LRESULT
'' entry point
Dim As HINSTANCE hInstance hInstance = GetModuleHandle(0) Dim wMsg As MSG Dim wcls As WNDCLASS Dim hWnd As HWND Dim As HWND hWndButton Dim As HWND hWndButton_ Dim As HWND hWndEdit Dim As HWND hWndButton2 Dim As HWND hWndButton_2 Dim As HWND hWndEdit2
Dim As String ClassName ClassName = "HelloWin"
With wcls .style = CS_HREDRAW Or CS_VREDRAW .lpfnWndProc = @WndProc .cbClsExtra = 0 .cbWndExtra = 0 .hInstance = hInstance .hIcon = LoadIcon( NULL, IDI_APPLICATION ) .hCursor = LoadCursor( NULL, IDC_ARROW ) .hbrBackground = GetStockObject( WHITE_BRUSH ) .lpszMenuName = NULL .lpszClassName = Strptr(ClassName) End With If( RegisterClass( @wcls ) = FALSE ) Then MessageBox( null, "Failed to register wcls", "Error", MB_ICONERROR ) End end If
hWnd = CreateWindowEx( WS_EX_CONTROLPARENT, _ Strptr(ClassName), _ "The Hello Program", _ WS_OVERLAPPEDWINDOW, _ 0, _ 0, _ 500, _ 500, _ NULL, _ NULL, _ hInstance, _ NULL ) hWndButton =CreateWindowEx( 0, _ WC_BUTTON, _ "Click me", _ WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or WS_GROUP, _ 20, _ 100, _ 70, _ 30, _ hWnd, _ NULL, _ hInstance, _ NULL ) SendMessage(hWndButton, WM_SETFONT, cast(WPARAM, GetStockObject(DEFAULT_GUI_FONT)),0)
hWndButton_ =CreateWindowEx( 0, _ WC_BUTTON, _ "Click me", _ WS_CHILD Or WS_VISIBLE Or WS_TABSTOP, _ 100, _ 100, _ 70, _ 30, _ hWnd, _ NULL, _ hInstance, _ NULL ) SendMessage(hWndButton_, WM_SETFONT, cast(WPARAM, GetStockObject(DEFAULT_GUI_FONT)),0)
hWndEdit =CreateWindowEx( WS_EX_CLIENTEDGE, _ WC_EDIT, _ "Text1", _ WS_CHILD Or WS_VISIBLE Or WS_TABSTOP, _ 200, _ 100, _ 70, _ 30, _ hWnd, _ NULL, _ hInstance, _ NULL ) SendMessage(hWndEdit, WM_SETFONT, cast(WPARAM, GetStockObject(DEFAULT_GUI_FONT)),0)
hWndButton2 =CreateWindowEx( 0, _ WC_BUTTON, _ "Click me too", _ WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or WS_GROUP, _ 20, _ 200, _ 70, _ 30, _ hWnd, _ NULL, _ hInstance, _ NULL ) SendMessage(hWndButton2, WM_SETFONT, cast(WPARAM, GetStockObject(DEFAULT_GUI_FONT)),0)
hWndButton_2 =CreateWindowEx( 0, _ WC_BUTTON, _ "Click me too", _ WS_CHILD Or WS_VISIBLE Or WS_TABSTOP, _ 100, _ 200, _ 70, _ 30, _ hWnd, _ NULL, _ hInstance, _ NULL ) SendMessage(hWndButton_2, WM_SETFONT, cast(WPARAM, GetStockObject(DEFAULT_GUI_FONT)),0)
hWndEdit2 =CreateWindowEx( WS_EX_CLIENTEDGE, _ WC_EDIT, _ "Text2", _ WS_CHILD Or WS_VISIBLE Or WS_TABSTOP, _ 200, _ 200, _ 70, _ 30, _ hWnd, _ NULL, _ hInstance, _ NULL ) SendMessage(hWndEdit2, WM_SETFONT, cast(WPARAM, GetStockObject(DEFAULT_GUI_FONT)),0)
ShowWindow( hWnd, SW_NORMAL ) UpdateWindow( hWnd )
While( GetMessage( @wMsg, NULL, 0, 0 ) <> FALSE ) If IsDialogMessage(hWnd, @wMsg) = 0 Then TranslateMessage( @wMsg ) DispatchMessage( @wMsg ) End If Wend
End wMsg.wParam
Function WndProc ( Byval hWnd As HWND, _ Byval wMsg As UINT, _ Byval wParam As WPARAM, _ Byval lParam As LPARAM ) As LRESULT Function = 0 Select Case( wMsg )
Case WM_DESTROY PostQuitMessage( 0 ) Exit Function End Select Function = DefWindowProc( hWnd, wMsg, wParam, lParam ) End Function |
WS_GROUP is not needed but allows the user to navigate through the controls of one group using the arrow keys (only is the control doesn't process the arrow keys, like the edit control), WS_EX_CONTROLPARENT is not needed here either, because all controls are directly childs of the main window..
WS_TABSTOP makes a control "reachable" with the TAB key.
Thanks guys for that trick with IsDialogMessage() cause that makes it working... |
| |
|
| Back to top |
|
 |
|
|
Posted: Apr 09, 2006 16:37 Post subject: |
|
|
| Thanks, fellas, WS_TABSTOP worked. Now: Just to figure out what the dillio is with XP themes. |
| |
|
| Back to top |
|
 |
|
|
|
| Back to top |
|
 |
|
|
Posted: Apr 09, 2006 17:53 Post subject: |
|
|
Uxtheme has a lot of useful functions, but none activate a theme for a window. I can use all the drawing functions in there with WM_DRAWITEM, but I'd rather not use all owner-drawn functions because that'll bloat the library with unnecessary code.
Right now the only way to do that I can think of is to use InitCommonControls() and make a manifest style.
But thanks for the tip, though, that's a handy reference page. |
| |
|
| Back to top |
|
 |
|
|
Posted: Apr 09, 2006 18:07 Post subject: |
|
|
| dunno.. but what about SetWindowTheme()? |
| |
|
| Back to top |
|
 |
|
|
Posted: Apr 09, 2006 18:42 Post subject: |
|
|
Just to note that because you're using IsDialogMessage, you no longer need this code:
| Code:
|
|
Case WM_KEYDOWN If( lobyte( wParam ) = 27 ) Then PostMessage( hWnd, WM_CLOSE, 0, 0 ) End If |
Instead, you can use:
| Code:
|
|
Case WM_COMMAND Select Case As Const LOWORD(wParam) Case IDCANCEL 'IDCANCEL = ESC key SendMessage(hWnd, WM_CLOSE, wParam, lParam) End Select |
------------
edit: hmm.. I can't compile the jinx code.. Where do I find the jinx files at? |
| |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|