PDA

View Full Version : Need Help on making Window creating class



kcvinu
03-03-2018, 15:32
Hi,
I am planning to make a class for making Windows gui easily with the help of win api functions. I am doing this for learning purpose.
And i wrote code for my class. This is the pseudo code.

In my class
1. There is a Window creating method which uses CreateWindoweEx function. Name = Window_Create( )
Parameters of that method is :
Window_Title = String
Pointer of WndProc function = Pointer
Width & Height, Position = Integer
WinStyles & WinExStyles = Long

It has following steps.
a. Getting the module handle
b. Declare and fill the WNDCLASS structure.
c. Registering window class with RegisterClassEx function.
d. Calling the so called CreateWindoweEx
e. This method returns the newly created window handle.
2. A Message Pump Sub routene. Name = MessagePump( )
It contains a while loop and GetMessage, TranslateMessage, and DispatchMessage functions.

3. A Sub routene to show the window. Name = ShowForm( )
It contains ;
a. ShowWindow function
b. UpdateWindow function.
c. MessagePump Sub

So in my main file looks like this;
a. Declare a WndProc function.
b. Create the instance of the class and call the Window_Create method.
c. Write the complete WndProc function.
d. Call the ShowForm( ) Sub

With this setup, i can get almost any window Messages but i couldn't handle the second window. Can anybody guide me to make this class able to handle more than one window ? Thanks in advance.
Note - I am making this class in FreeBasic language. But i thought that this is a logic problem rather than a language problem. Correct me if i am wrong.

ErosOlmi
05-03-2018, 22:10
Ciao,

I do not understand if you are asking in order to create a thinBasic script or for developing in Freebasic.
In thinBasic it is not possible to pass a script Functions pointer to a windows API because there is no compiled function to have a pointer to.
So using classical RegisterClassEx api passing you window class and inside that a pointer to a function it not possible from a script
You need program into a language able to create real executables. thinBasic do not create such king of executables.

But let me know, maybe I misunderstood your request.
Eros

kcvinu
06-03-2018, 10:21
Hi Eros,
Let me explain my question a bit.
Here is the 'Reason' of my whole question.
In thinbasic we are using a callback function without any params and we can also use some macros like cbCtl, cbHNDL. I like this style. So i want to implement this style in FreeBasic. And i create my own gui library with windows api functions. But i cant create a callback function setup. I know that behind the scene, a wndproc function is working for us in thinbasic. But it is hidden. Programmer only see and use the callback function. How does it is possible ?

Edit Note :- By the way, Jose Roca has created a CWstr library for FreeBasic. Its amazing. With that lib, we can easily use dynamic unicode string in our program. I know that you are working on a new version of thinBasic which supports unicode. I think it is worth checking that lib.
FreeBasic has a fixed length wid string data type. Jose roca made it a fully dynamic unicode string.

zlatkoAB
06-03-2018, 20:08
Eros answer to you properly...
So if you think to create WindowsClass you must use native compiler.
If is not problem you may look in Oxygen Basic forum
where you can find some examples ;

like:


Type WNDCLASSEX
cbSize as long
Style as long
lpfnwndproc as long
cbClsextra as long
cbWndExtra as long
hInstance as long
hIcon as long
hCursor as long
hbrBackground as long
lpszMenuName as long
lpszClassName as long
hIconSm AS long
End Type

and this:


Function SetWindow (byval caption as string ,byval Wx as int,byval Wy as int, byval Ww as int, byval Wh as int, byval wparent as int, byval style as int) as int
inst = GetModuleHandle 0
'sys hbrush=RGB(250,250,255)
wcx.cbSize = sizeof(WNDCLASSEX)
wcx.style = CS_DBLCLKS |CS_OWNDC
wcx.lpfnWndProc = &WndProc
wcx.cbClsExtra =0
wcx.cbWndExtra =0
wcx.hInstance = inst
wcx.hIcon =LoadIcon 0,IDI_APPLICATION
wcx.hCursor =LoadCursor 0,IDC_ARROW
wcx.hbrBackground = CreateSolidBrush(GetSysColor(15))
wcx.lpszMenuName = ?0
wcx.lpszClassName = @"Oxygen"
wcx.hIconSm =LoadIcon 0,IDI_APPLICATION

RegisterClassEx &wcx

I hope that help ..

kcvinu
06-03-2018, 22:04
@zlatkoAB,
Hi, thanks for your reply. But as i stated my above comment, Registerclass is not my real problem. I am planning to hide WndProc from user. So i need a function which mimics WndProc but hide its complexities. Just like the CallBack function in thinBasic. At first, i thought that RegisterClass will do this trick for me. But after some google search and little experiments, i have realized that my assumption were wrong. Thanks for guiding me to OxygenBasic forum. Let me check.

ErosOlmi
06-03-2018, 23:25
Ciao,

yes, I always follow Jose development in any forum he posts :)
Is like following a great guru always having something to teach and for inspiration.

Anyway ... back to your question: how do I'm able to use script functions as callbacks?
The story is long but I will try to short it and then enter in few details if needed:

first create your window in the way you prefer
when you have your window, inside WM_CREATE message, allocate (once) a pointer into window user data. I use PowerBasic so acceding a dialog user data is as easy as using DIALOG SET/GET ... one of the 8 user data slot PowerBasic give to you
what do I allocate to that pointer? a pointer to a user defined type (a structure) in which I store any info I need to recall when needed. In my case actually I store 23 longs (23 * sizeof(long) array)
one of those element is a pointer to my script function internal data that the user has decided to use as window callback
when your real window callback function is called by the windows message pump, first of all GET your user data allocated during WM_CREATE, get your pointer, get the data you need
in my case I get the pointer to the script callback function
having that pointer, I can pass event data to my script function


That's the short story.
The very long story is about 10k lines of code :) just for handling windows events

In any case let me know if you need more details

Ciao
Eros

kcvinu
07-03-2018, 10:31
@Eros,
Hi, Thanks for this well explained reply. I got a basic idea that i need to set the user's callback function's address with the help of SetWindowLongPtr function. And the flag is "GWLP_USERDATA". Am i right. But i am confused with this idea. This is my assumption, please correct me if i am wrong.

This is in my window class.
1. Register window class
2. Create window and controls
3. Write a WndProc function.
4. In the WM_CREATE msg, use SetWindowLongPtr

Thats ok, but how do i know that a WM_LBUTTONUP is occurred in the program ? In my concept, OS knows the address of my WndProc function. So it call that function when any events are happen. Say a WM_LBUTTONUP happened, but i didn't write anything related to WM_LBUTTONUP in my WndProc. So how do i route it to user's callback function ? Or do i need to write all possible windows messages in WndProc functon and tell it to call the user's callback function ?

ErosOlmi
07-03-2018, 10:58
I do not want you to go on the wrong track so I will reply under the hypotheses you are asking not for integrating thinBasic script but in general.
To be able to do something like what we are talking about in thinBasic you need to write a compiled module, impossible inside a script.

But talking in general, yes what you wrote is the general idea.
In WM_CREATE of window class callback you setup what you need.
Then inside window class callback in any message you need to pass to your personalized function, call your function passing WHNDL, MSG, WPARAM, LPARAM, ...
Another way is to pass all messages to your personalized function returning true/false depending if you have handled the message.
If yes, just exit
If no, process the message inside window class callback

kcvinu
07-03-2018, 19:07
@Eros,
Hi, Now, i am going to experiment something what i understood from your reply. :)

kcvinu
12-03-2018, 20:01
@Eros,
Hi, i am glad to write this because, i just succeeded to bypass WndProc function without setting any special data in window creation time. This is the steps.
1. I wrote all window creation functions in a module.
2. I wrote a WndProc function too in that module.
3. Now user can declare a callback function in their main file. like - SetCallBack(Ptr_of_callback_function). This function call should be done before window creation.
4. I just used this callback function inside my WndProc function with that pointer.
5. In my module, i declared some global variables like-
WinHndl = Window Handle
WinMsg = a UINT message
CtlHndl = a Control handle extracted from wParam in WM_COMMAND.
Now, i am planning to extract control handle from WM_NOTIFY command too.

But the problems are;
1. Main window is hung when a second window created.
2. All windows will close when any of the window is closed.

Any suggestions how to deal this ? Thanks in advance.

ErosOlmi
12-03-2018, 21:48
Problem 1:
it seems you have used MODAL windows. Modal Windows do not return control to main application until they are closed.
You need to have modeless windows each with its window message plus a a global message pump

Problem 2:
not sure, maybe you are passing over the quit command from last window to main window.
Also you need to keep track how many windows are still there and close only when needed.

I still do not understand under which programming language are you developing :)

kcvinu
12-03-2018, 22:02
@Eros,
Thanks for the reply. I will sure check about MODAL windows.
Anyway, i have managed to fix the window closing issue. I just create a Global variabale in my module and keep the First window's (Main WIndow) handle on it. Besides that, i wrote an extra function in this module to create child windows for this main window. So in WndProc, i can handle WM_DESTROY msg with the window handle of MainWindow.

I am coding this in FreeBasic. One thing i forgot to mention. I got a chance to learn a lot about win api in Frederick J Harris's tutorial on PowerBasic forum. Its really a wealth of information. In that tutorial, he wrote about how .Net handle the WndProc function with so many handler functions like OnClick, OnPaint, OnLoad etc.

ErosOlmi
12-03-2018, 23:00
Eheh :D
There will be great new features in thinBasic too under that aspect.

The following is a thinBasic script working under the next thinBasic 1.10.5 I will release hopefully shortly.
Every window or control will have the possibility to have an optional NAME
And using that name plus the name of the event, you will be able to handle most of the events with easy function names.
All into an interpreted source code script.



USES "UI"
uses "console"
uses "Registry"


'---Define a button ID
begin ControlID
%ButtonClose
%ButtonSearch
%lblFind
%txtFind
%lblReplace
%txtReplace
end ControlID




DIALOG New Pixels, Name MyWindow, 0, "Dialog to show automatic events handling",-1,-1, 640, 480,
%WS_DLGFRAME | %DS_CENTER | %WS_CAPTION | %WS_SYSMENU | %WS_OVERLAPPEDWINDOW


CONTROL ADD Label Name lblFind , MyWindow.Handle, %lblFind , "Find" , 10, 15, 350, 20, %SS_NOTIFY
CONTROL ADD Textbox Name txtFind , MyWindow.Handle, %txtFind , "" , 10, 30, 350, 25, %ES_AUTOHSCROLL | %ES_LEFT | %WS_BORDER | %WS_TABSTOP


CONTROL ADD Label Name lblReplace , MyWindow.Handle, %lblReplace , "Replace" , 10, 55, 350, 20, %SS_NOTIFY
CONTROL ADD Textbox Name txtReplace , MyWindow.Handle, %txtReplace , "" , 10, 70, 350, 25, %ES_AUTOHSCROLL | %ES_LEFT | %WS_BORDER | %WS_TABSTOP




CONTROL ADD BUTTON Name btnSearch , MyWindow.Handle, %ButtonSearch, "Search" , 480, 10, 150, 25, %BS_NOTIFY | %BS_CENTER | %BS_VCENTER | %WS_TABSTOP
CONTROL ADD BUTTON Name btnCloseMe , MyWindow.Handle, %ButtonClose , "Close" , 480, 40, 150, 25, %BS_NOTIFY | %BS_CENTER | %BS_VCENTER | %WS_TABSTOP






DIALOG SHOW MODAL MyWindow.Handle




'------------------------------------------------
' Callback function used to handle dialog events
' not handled by specific event functions
'------------------------------------------------
CallBack Function MyWindow_OnCallBack() As Long
'------------------------------------------------


'printl Timer, Function_Name, CBMSG, MyWindow.Name & ": message not handled by specific event function"


End Function


'------------------------------------------------
CallBack Function MyWindow_OnInit() As Long
'------------------------------------------------


printl Timer, Function_Name


'---Limits window minimum size
DIALOG SET MINSIZE CBHNDL, 550, 220

control set Resize CBHNDL, %ButtonSearch, 0, 1, 0, 0
control set Resize CBHNDL, %ButtonClose , 0, 1, 0, 0


txtFind.Text = "TextToFind"
txtReplace.Text = "TextToReplace"
btnCloseMe.Text = "Close Me"


End Function


'------------------------------------------------
CallBack Function MyWindow_OnSize() As Long
'------------------------------------------------

printl Timer, Function_Name, MyWindow.X, MyWindow.Y, MyWindow.W, MyWindow.H


End Function


'------------------------------------------------
CallBack Function MyWindow_OnMove() As Long
'------------------------------------------------


printl Timer, Function_Name, MyWindow.X, MyWindow.Y, MyWindow.W, MyWindow.H


End Function


'------------------------------------------------
CallBack Function MyWindow_OnMoving() As Long
'------------------------------------------------


printl Timer, Function_Name


End Function


'------------------------------------------------
CallBack Function MyWindow_OnMouseMove() As Long
'------------------------------------------------


printl Timer, Function_Name


End Function


'------------------------------------------------
CallBack Function MyWindow_OnNCHITTEST() As Long
'------------------------------------------------


printl Timer, Function_Name


End Function


'------------------------------------------------
CallBack Function MyWindow_OnSETCURSOR() As Long
'------------------------------------------------


printl Timer, Function_Name


End Function


'------------------------------------------------
CallBack Function MyWindow_OnLBUTTONDOWN() As Long
'------------------------------------------------


printl Timer, Function_Name


End Function


'------------------------------------------------
CallBack Function MyWindow_OnLBUTTONUP() As Long
'------------------------------------------------


printl Timer, Function_Name


End Function


'------------------------------------------------
CallBack Function MyWindow_OnLBUTTONDBLCLK() As Long
'------------------------------------------------


printl Timer, Function_Name


End Function


'------------------------------------------------
CallBack Function MyWindow_OnNCMOUSEMOVE() As Long
'------------------------------------------------


printl Timer, Function_Name


End Function


'------------------------------------------------
CallBack Function MyWindow_OnNCMOUSELEAVE() As Long
'------------------------------------------------


printl Timer, Function_Name


End Function


'------------------------------------------------
CallBack Function MyWindow_OnCommand() As Long
'------------------------------------------------


printl Timer, Function_Name

End Function


'------------------------------------------------
CallBack Function MyWindow_OnClose() As Long
'------------------------------------------------


printl Timer, Function_Name


End Function


'------------------------------------------------
CallBack Function MyWindow_OnSHOWWINDOW() As Long
'------------------------------------------------


printl Timer, Function_Name


End Function


'------------------------------------------------
CallBack Function MyWindow_OnDestroy() As Long
'------------------------------------------------


printl Timer, Function_Name
PrintL "Window just destroyed. Press a key to end" in %CCOLOR_FLIGHTRED
WaitKey


End Function






'------------------------------------------------------------------------------
' BUTTON EVENT
'------------------------------------------------------------------------------


'------------------------------------------------
CallBack Function btnCloseMe_OnClick() As Long
'------------------------------------------------


printl Timer, Function_Name, btnCloseMe.Name
DIALOG End CBHNDL


End Function


'------------------------------------------------
CallBack Function btnCloseMe_OnSetFocus() As Long
'------------------------------------------------


printl Timer, Function_Name, btnCloseMe.Name


End Function


'------------------------------------------------
CallBack Function btnCloseMe_OnKillFocus() As Long
'------------------------------------------------


printl Timer, Function_Name, btnCloseMe.Name


End Function


'------------------------------------------------
CallBack Function btnSearch_OnClick() As Long
'------------------------------------------------


printl Timer, Function_Name, btnSearch.Name, "Search clicked, something new should happen :)"


End Function


'------------------------------------------------------------------------------
' LABEL EVENT
'------------------------------------------------------------------------------


'------------------------------------------------
CallBack Function lblFind_OnClick() As Long
'------------------------------------------------


printl Timer, Function_Name, lblFind.Name


End Function


'------------------------------------------------
CallBack Function lblFind_OnDblClk() As Long
'------------------------------------------------


printl Timer, Function_Name, lblFind.Name


End Function


'------------------------------------------------
CallBack Function lblFind_OnDisable() As Long
'------------------------------------------------


printl Timer, Function_Name, lblFind.Name


End Function


'------------------------------------------------
CallBack Function lblFind_OnEnable() As Long
'------------------------------------------------


printl Timer, Function_Name, lblFind.Name


End Function




'------------------------------------------------------------------------------
' TEXTBOX EVENT
'------------------------------------------------------------------------------


'------------------------------------------------
CallBack Function txtFind_OnCallback() As Long
'------------------------------------------------


printl Timer, Function_Name, CBCTLMSG, txtFind.Name
Function = %TRUE


End Function




'------------------------------------------------
CallBack Function txtFind_OnChange() As Long
'------------------------------------------------


printl Timer, Function_Name, "text changed in control ", txtFind.Name
printl txtFind.Text in %CCOLOR_FLIGHTCYAN


Function = %TRUE


End Function


'------------------------------------------------
CallBack Function txtFind_OnUpdate() As Long
'------------------------------------------------


printl Timer, Function_Name, txtFind.Name
Function = %TRUE

End Function


'------------------------------------------------
CallBack Function txtFind_OnSetFocus() As Long
'------------------------------------------------
txtFind.backcolor = %RGB_THISTLE
printl Timer, Function_Name, txtFind.Name

End Function


'------------------------------------------------
CallBack Function txtFind_OnKillFocus() As Long
'------------------------------------------------


txtFind.backcolor = %RGB_WHITE
printl Timer, Function_Name, txtFind.Name

End Function


'------------------------------------------------
CallBack Function txtReplace_OnChange() As Long
'------------------------------------------------


printl Timer, Function_Name, "text changed in control ", txtReplace.Name
printl txtReplace.Text in %CCOLOR_FLIGHTCYAN
Function = %TRUE


End Function


'------------------------------------------------
CallBack Function txtReplace_OnUpdate() As Long
'------------------------------------------------


printl Timer, Function_Name, txtReplace.Name
Function = %TRUE

End Function


'------------------------------------------------
CallBack Function txtReplace_OnSetFocus() As Long
'------------------------------------------------


txtReplace.backcolor = %RGB_AQUAMARINE
printl Timer, Function_Name, txtReplace.Name

End Function


'------------------------------------------------
CallBack Function txtReplace_OnKillFocus() As Long
'------------------------------------------------


txtReplace.backcolor = %RGB_WHITE
printl Timer, Function_Name, txtReplace.Name

End Function

ReneMiner
14-03-2018, 13:50
Reads good so far :)

Were it possible to make the event-callback-functions to receive the user-property of the controls?

For example I have some images to display and I give all image-controls the same name and every image-control an index-number -
could be stored in the user-slots
(Control Set User...)-
Now assumed one of the images gets clicked and within the events callback I want to know the images index:



Callback Function myimage_OnLeftButtonDown(Optional Userdata(4) As Long) As Long

Or is there another way to retrieve the desired data stored at the control?