PDA

View Full Version : CreateWindowEx is resulting Zero.



kcvinu
03-04-2021, 09:29
Hi all,
I am trying to create a window with win32 functions. But CreateWindowEx is returning 0 . This is my code. Please check this and guide me.



Uses "Console"

Type tWNDCLASSEX
cbSize as DWord
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

Type tPoint
x As dword
y as dword
end type

Type tMsg
hwnd as Long
message as Long
wParam as Long
lParam as Long
time as DWord
pt as tPoint
lPrivate as DWord
end type

Declare Function GetModuleHandle Lib "Kernel32.dll" Alias "GetModuleHandleW"(ByVal lpModuleName as Long) As Long
Declare Function LoadIcon Lib "User32.dll" Alias "LoadIconW"(ByVal hInstance as Long, ByVal lpIconName As Long) As Long
Declare Function LoadCursor Lib "User32.dll" Alias "LoadCursorW"( ByVal hInstance as Long, ByVal lpIconName As Long) As Long
Declare Function RegisterClassEx Lib "User32.dll" Alias "RegisterClassExW" (pcWndClassEx As tWNDCLASSEX) As DWord
Declare Function GetStockObject Lib "Gdi32.dll" Alias "GetStockObject" (ByVal nIndex As Long) As Long
Declare Function CreateWindowEx Lib "User32.dll" Alias "CreateWindowExW" (ByVal dwExStyle As DWord, ByVal lpClassName As Long, ByVal lpWindowName As Long, ByVal dwStyle As DWord, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, ByVal lpParam As Long) As Long
Declare Function ShowWindow Lib "User32.dll"(ByVal lhwnd As Long, ByVal nCmdShow As Long) As Long
Declare Function UpdateWindow Lib "User32.dll" (ByVal lhwnd As Long) As Long
Declare Function DefWindowProc Lib "User32.dll" Alias "DefWindowProcW" (ByVal lhwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'// Declare Function GetMessage Lib "User32.dll" Alias "GetMessageW" (ByRef lpMsg As tMsg, ByVal lhwnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long) As Long
Declare Function TranslateMessage Lib "User32.dll" Alias "TranslateMessageW" (ByRef lpMsg As tMsg) As Long
Declare Function DispatchMessage Lib "User32.dll" Alias "DispatchMessageW" (ByRef lpMsg As tMsg) As Long


Function MakeIntRs(i As Long) As Variant
Dim temp As Long = i AND 0xffff
Function = temp
End Function



Dim CSVREDRAW = 0x0001
Dim CSHREDRAW = 0x0002
Dim CSDBLCLKS = 0x0008
Dim IDC_ARROW = MakeIntRs(32512) '// I am getting zero as value !
Dim IDI_APPLICATION = MakeIntRs(32512)
Dim My_OVERLAPPEDWINDOW As DWord = 0x00000000 OR 0x00C00000 OR 0x00080000 OR 0x00040000 OR 0x00020000 OR 0x00010000
Dim SWSHOW As Long = 5

'// %'CS_OWNDC = 0x0020 '// These equates are not working !!!!

Type Application
ClassName As Asciiz
hInstance as DWord

Function RegWindow()
Dim wndClsx As tWNDCLASSEX
me.ClassName = "ThinBasic Window"
me.hInstance = GetModuleHandle(0)
with wndClsx
.cbSize = SizeOf(wndClsx)
.style = CSHREDRAW OR CSVREDRAW OR CSDBLCLKS
.lpfnWndProc = Function_GetPtr(WndProc) '// is this the correct way of getting a function pointer ?
.cbClsExtra = 0
.cbWndExtra = 0
.hInstance = me.hInstance
.hIcon = LoadIcon(0, IDI_APPLICATION)
.hCursor = LoadCursor(0, IDC_ARROW)
.hbrBackground = GetStockObject(0)
.lpszMenuName = 0
.lpszClassName = StrPtr(me.ClassName)
'// .hIconSm = 0
End With

if RegisterClassEx(wndClsx) = 0 Then '// Well, this is success.
MsgBox("Window Registration Failed")
EndIf

PrintL PEEK$(ASCIIZ, wndClsx.lpszClassName)
End Function
End Type

Function WndProc(h As Long, msg As Long, wp As Long, lp As Long)
Function = DefWindowProc(h, msg, wp, lp)
End Function

Dim ap as Application
ap.RegWindow()

dim wname As Asciiz = "My Thin Window"
dim pWn As Long = StrPtr(wname)
Dim hwn As Long = CreateWindowEx(0, ap.ClassName, wname, My_OVERLAPPEDWINDOW, 10, 10, 400, 400, 0, 0, ap.hInstance, NULL) '// Main problem lies on this function call.
PrintL("Window Handle - ", hwn) '// This will print a zero.
PrintL(ap.hInstance) '// But this will print a number.

if hwn > 0 Then
ShowWindow(hwn, 5)
UpdateWindow(hwn)

Dim uMsg As tMsg
While Win_GetMessage(uMsg, hWnd, 0, 0) <> 0
TranslateMessage(uMsg)
DispatchMessage(uMsg)
Wend

Else
MsgBox("Window creation Failed..!")
EndIf

WaitKey

ReneMiner
05-04-2021, 01:14
am not sure but if you want ti create a windowvlass of the medieval generation there was something to do as calling to initcommon controls checl the tninbasic sample files - i think tjhere washidden on a folcer before ui in a folder hidden behind an example how to load the win32 controls library and use its functions,

kcvinu
05-04-2021, 05:00
@ReneMiner

Thanks for the reply. But there is some include files are missing.
1. "APPUTILS.INC"
2. "APPPROPS.INC"

If i get these files, i can try. This is the path of that script.
C:\thinBasic\SampleScripts\UI\SDK
In that folder, i couldn't find the include files. If you have them, I request you to kindly upload those. Thanks in advance.

ReneMiner
05-04-2021, 06:09
no its function?getPtr. the code is not compiled so are no real function pointers, use codeptr (https://www.thinbasic.com/public/products/thinBasic/help/html/codeptr.htm) and (https://www.thinbasic.com/public/products/thinBasic/help/html/codeptr.htm) read the manual (https://www.thinbasic.com/public/products/thinBasic/help/html/codeptr.htm) hpw thinbasic-users can get around this individuality
i meant the scripts i attchhed here, - it might be right on time for your curren studies / and i think ius 3 scripts of 2 different projects

kcvinu
05-04-2021, 23:17
@ReneMiner
Suddenly it worked !!!.
After losing hope, I've decided to do some experiments with data types. So I started changing lpWindowName parameter. But my problem area was lpClassName's type.
So after wasting some time, i decided to experiment with class name. I prefer "Long" since the parameter name starts with lp aka Long ptr. Then i tried Varptr in calling site. And voilą ! It worked all of a sudden. Anyhow, thanks for the scripts. Let me check them. Thanks for the support. At last, i have made my unicode aware window in thinBasic. Now, its time to wrap those things up in a class and write some properties & methods.

BTW, there was no way for me to understand what is the error but just guessing. Now i want to learn about thinBasic's include file. All the include file i have seen was only contains the function declarations. Can i use them for function & class implementation ?

ReneMiner
06-04-2021, 16:47
you can use any tpye of script for what you like,
Even possible to make your own filetypes and extensions but thinAir will complain. But thincore executes everything. Importan that it must have an app/entrypoint (TBMain mostly.) but App_Entrypoint is a function to use alternatives.That might be useful if you develop something that should run on different systems Win on x64 or x86 or in WINE or react-OS etc.

I use thinBasics scripttypes as

.tBasic - always the script containing function tbMain and especially for the current app developed functions

.tBasicC - plain console only.

.tBasicI - include files / those are mostly re/useable declarations, wrappers/headers and allround-functions as you might separate the function for printing a page and not to contain it to the mainfile so in your next projct the already well/tested specialization is embedded with 1 line only. i prefer to use include for imported stuff or that translated from other languages

.tBasicU- thinbasic unit files is what i use for plain thinbasiccode without any external dependencies, preferable for UDTs wher the first line of a unit is actually


' info text very interesting lalala

#MinVersion 1.2.3.4
' date always good to know what was available / what features were new that time...
' written in sepobruary 2123

' about this and that and this
' unit is based on tMyBasetype that is an inflateable SabertoothTiger:
'
#Include Once "tMyBasetype.tBasicU"

' now already included because required...
' this is a splitteable Mammooth that allows to turn times back
' when fed with ancient data


Type tMyType [ Extends tMyBasetype ]
[properties]
static enum as ...assign to shared& defaults to all objects of this type
' already before any variable was declared
...A As B
C As D
Functions to be used on this type...
'... etc

End Type


so these are really Units. completely enclosed no loose code but only what is within Type and End Type.
Exceptional are #Preparsing/Statements or necessary declarations that are required for one or more functions of that type
So i am sure that i can embedd -what ever i wrote - in one piece .

Actually i use one selfmade type of file with an extension as ".thinBasic" that is alike a project-file and contains no real code but only directives and preparsing statements, declarations, included Files and global variable dimensioning (if any)
when all those things are setup it comes to load the final unit; the main script, containing subs and functions, some callbacks possibly and as last of the script i place tbMain to avoid any error that a function were unknown i let the parser run over everything before execution is performed.
And i have some fake/scripttype, also named ".thinBasic", registered as "thinBasic.Project.File" and to open with thinBasic.exe. It has right in the classes root a "ShellNew"'-command attached and the Data/Setting is a tiny script Uses "console" and "OS"
checks the OS_GetCommand(1) for its own name and the folder inside that it was called after i double-clicked the file to know where i wanted the location of my new project

ip if its own name still contains "New" and "thinBasic". if yes it opens a common doalog to browse for the location where the projectfolder is to create. The folders name or the name of the script if changed becomes the project name, either the file was renamed or not, the files name will give the folder a name and create it and place a script template inside that i selected from a list, renamed to be the <Projectname>_Main.tBasic
it creates a skeleton using #Region "Directives" & #EndRegion, #Region "External Sources" etc until #Region "Global Variables".

"TheNewthinBasic.Project.File# that was in the directory where is now a new projectfolder vanished already and inside of the folder are 2 scripts already named before i start to write a line of code.

kcvinu
06-04-2021, 20:47
@ReneMiner,
Thanks for the detailed reply.
I don't know life is full of obstacles in thinBasic. Here is my declaration of my CreateWindowEx.


Declare Function CreateWindowEx Lib "User32.dll" Alias "CreateWindowExW" (ByVal dwExStyle As DWord, _
Byval lpClassName As Long, _
Byval lpWindowName As WStringZ, _
ByVal dwStyle As DWord, _
ByVal x As Long, ByVal y As Long, _
ByVal nWidth As Long, ByVal nHeight As Long, _
ByVal hWndParent As DWord, _
ByVal hMenu As DWord, _
ByVal hInstance As DWord, _
lpParam As Any) As DWord

And here is my window craetion code. It is working like a charm.


dim WinTxt As String = "My Window"
dim WinClass As String = "ThinBasic Window"
dim hInsta As DWord = GetCurrentInstance

Dim hwn As DWord = CreateWindowEx(0, VarPtr(WinClass ), WinTxt ,
%WS_OVERLAPPEDWINDOW,
600, 100, 700, 400,
%HWND_DESKTOP, %NULL,
hInsta, %NULL)


Now, i use CreateWindowEx again to create a button but it's not working. Here is the button creation code.


Dim btxt as string = "Click Me"
Dim bc As String= "Button"
Dim bhwn As DWord = CreateWindowEx(0, Varptr(bc), btxt ,
%WS_CHILD or %WS_VISIBLE,
140, 120, 150, 50,
hwn, %NULL,
hInsta,
%NULL)
PrintL("Button handle ", bhwn) '\\ This is printing zero.

Same function declaration. Same data types. But one is working, another is not.

ErosOlmi
07-04-2021, 12:19
Ciao,

just to let you know I'm following this thread testing what you are trying to do and see if there are problems from thinBasic side.

I can confirm there is something I need to fix and release in next thinBasic version.
I found a big bug in CodePtr function and possibly some problems in passing parameters in external declared functions.

I will be more precise in next days and possibly release a new thinBasic version with the fixes.

Ciao
Eros

ErosOlmi
07-04-2021, 14:21
Now, i use CreateWindowEx again to create a button but it's not working. Here is the button creation code.


Dim btxt as string = "Click Me"
Dim bc As String= "Button"
Dim bhwn As DWord = CreateWindowEx(0, Varptr(bc), btxt ,
%WS_CHILD or %WS_VISIBLE,
140, 120, 150, 50,
hwn, %NULL,
hInsta,
%NULL)
PrintL("Button handle ", bhwn) '\\ This is printing zero.

Same function declaration. Same data types. But one is working, another is not.

Try to change

Dim bc As String= "Button"
to

Dim bc As String= UTF8ToWideChar$("button")

And use StrPtr (not VarPtr) to return the pointer to the first byte of a dynamic string

kcvinu
07-04-2021, 21:39
@ErosOlmi,
Thanks for your help. I am glad that you are following this thread and improving thinBasic. I tried your suggestions and this the scenario which worked for me.
In the function declaration of CreteWindowEx, this is enough.


Byval lpClassName As Long, _
Byval lpWindowName As String, _ '// Yes, it worked with just string


And in the window creation site,


dim clsName As String = UTF8ToWideChar$("ThinBasic Window")
dim WinText As String = UTF8ToWideChar$("ThinBasic Unicode Window")
Dim hwn As DWord = CreateWindowEx(0, VarPtr(clsName ), WinText , '// Yes !!! Strptr is not worked here.
%WS_OVERLAPPEDWINDOW,
600, 100, 700, 400,
%HWND_DESKTOP, %NULL,
hInsta, %NULL)

So far so good. Now, the interesting part is the button creation.


Dim btxt as string = UTF8ToWideChar$("Unicode Button")
Dim bc As String= UTF8ToWideChar$("button")
Dim bhwn as DWord = CreateWindowEx(0, StrPtr(bc), btxt, '// Surprisingly, Varptr not worked here. But Strptr worked like a charm.
btnStyle,
140, 120, 150, 50,
hwn, 101,
hInsta,
0)

See the differences ?

kcvinu
08-04-2021, 23:22
@Eros Olmi
Hi,
How do i use the Window type in Wndproc function ? This is how i store my current Window type. This is working perfectly. No error.


Dim PtrMe As Long = VarPtr(Me
SetWindowLong(Me.WinHandle, -21, PtrMe) '// Varptr(Me) inside the function is not working


But I cannot use SetWindowLongPtr. What will be the reason ? Here is the function declarations.


Declare Function GetWindowLong Lib "User32.dll" Alias "GetWindowLongW"(ByVal hWnd As DWord, ByVal nIndex as Integer) As Long

Declare Function SetWindowLong Lib "User32.dll" Alias "SetWindowLongW"(ByVal hWnd As DWord,
ByVal nIndex as Integer,
ByRef dwNewLong As Long ) As Long

Declare Function GetWindowLongPtr Lib "User32.dll" Alias "GetWindowLongPtrW"(ByVal hWnd As DWord, ByVal nIndex as Integer) As Long

Declare Function SetWindowLongPtr Lib "User32.dll" Alias "SetWindowLongPtrW"(ByVal hWnd As DWord,
ByVal nIndex as Integer,
ByRef dwNewLong As Long ) As Long



And the main thing, I am able to get the Window type in WndProc with this code.


Dim win As TWindow = GetWindowLong(hwnd, -21)

But this is not the actual pointer. See this scenario
Step 1 - I create a tWindow type The default value of text property is "Window_01"
Step 2 - I change the text property of TWindow type with a member function, - win.SetTitle("bla bla")
Step 3 - I create the window with CreateWindowEx and use the SetWindowLong function to keep the TWindow pointer.
Step 4 - I retrieve the window type inside the WndProc function with GetWindowLong function.
Step 5 - On WM_LBUTTONDOWN, I try to print out the TWindow type's text property. But output is ""Window_01". Not "bla bla"
That means, the pointer i set using SetWindowLong and the pointer i get with GetWindowLong are different. How to fix this ?

I have a strong feeling that ThinBasic needs a List data type to hold not only the primitive data types like Integer, String, but also UDTs. A list, in which we dont need to use redim. And We now have a function to get a variables pointer with "Varptr". But we need a function to get the variable from that pointer.

Edit :
Basically, this is what i am trying to do.


#Include ".\ThinUi\*"

Dim win As TWindow '// Declare a new Window class
win.SetTitle("തിൻബേസിക്ക്") '// Set new title
win.SetSize(1000, 500) '// Set new size
win.Create() '// Create the actual window

'// Connect the mouse down event to user defined function. (NOT WORKING)
win.AddHandler(win.MouseDown, CodePtr(OnMouseClick))

'// user defined function. I want to add two parameters for this.
Function OnMouseClick() As Long
Printl("Window clicked")
End Function

'// Display the window
win.Display()