Simple WinAPI GUI library

User projects written in or related to FreeBASIC.
Lothar Schirm
Posts: 436
Joined: Sep 28, 2013 15:08
Location: Germany

Re: Simple WinAPI GUI library

Post by Lothar Schirm »

So I will include the combobox into WinGUI.bi. This will be done easily since you have already done the coding. Thank you!
Lothar
Lothar Schirm
Posts: 436
Joined: Sep 28, 2013 15:08
Location: Germany

Re: Simple WinAPI GUI library

Post by Lothar Schirm »

New update (see first post). I added the ComboBox and RNB's example from July 11.
Lothar Schirm
Posts: 436
Joined: Sep 28, 2013 15:08
Location: Germany

Re: Simple WinAPI GUI library

Post by Lothar Schirm »

New update on October 12, 2016 (see first post).

Changes:
- Function Window_New: Window style can be changed (new parameter "style" in the parameter list)
- In previous versions, adding, deleting or replacing an item in a listbox or combobox by an empty string caused the program to crash. This has been fixed.
Lothar Schirm
Posts: 436
Joined: Sep 28, 2013 15:08
Location: Germany

Re: Simple WinAPI GUI library

Post by Lothar Schirm »

New update on October 20, 2016.

It is now possible to change between controls or group of controls using the TAB key. See description in the Sub WaitEvent in WinGUI.bi. WaitEvent has been changed accordingly, and all active controls have a WS_TABSTOP style in the parameter list of the function which creates the control (e.g. Button_New, EditBox_New, ...).
Lothar Schirm
Posts: 436
Joined: Sep 28, 2013 15:08
Location: Germany

Re: Simple WinAPI GUI library

Post by Lothar Schirm »

New update on October 27, 2016.

Changes:
- Chr(0) was not removed when a text was retrieved from a control, this is corrected
- Style "ES_WANTRETURN" added to the Editor (multiline editbox)
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: Simple WinAPI GUI library

Post by datwill310 »

Hi Lothar,

This post is about the WinDialogs.bi header file (which, I understand is not entirely written by you, but I thought you could help me). I've been trying to use the loadsavedialog function, and it works, almost...

My filter string isn't working, and neither is your example in the comments?

Here's my code:

Code: Select all

filename = loadsavedialog(, "StoryScript (*.sts)"+chr(0)+"*.sts"+chr(0)+"All Files"+chr(0)+"*.*")
And before you tell me that I haven't ended it with chr(0, 0), I would like to point out this line in the function:

Code: Select all

dim strFilter as string
'default if filter = ""
if filter = "" then strFilter = "All Files (*.*)" + chr(0) +"*.*" + chr(0, 0) else strFilter = filter + chr(0, 0) '<----- So the function automatically adds the last two NULL chars?
FB_OFN.lpstrFilter = strptr(strFilter)
FB_OFN.nFilterIndex = fltrindex
If this is the case (that the two NULL chars are automatically appended), I think it's a little misleading that your example includes those two characters:

Code: Select all

'example for a filter:
'---------------------
'Dim As String fil
'fil = "Basic Files (*.bas)" + Chr(0) + "*.bas" + Chr(0) _
'  + "Text Files (*.txt)" + Chr(0) + "*.txt" + Chr(0)_
'  + "Image Files (*.bmp)" + Chr(0) + "*.bmp" + Chr(0)_
'  + "Executable Files (*.exe)" + Chr(0) + "*.exe" + Chr(0)_
'  + "All Files (*.*)" + Chr(0) + "*.*" + Chr(0, 0) <------ here
As I have said before, your library is great! But I have no idea what on earth is going on with the filters (I'm pretty sure this worked before too...).

My command line switches:

"C:\Program Files (x86)\FreeBASIC (32-bit)\fbc.exe" -s console "C:\Users\User\Documents\Free BASIC\StoryScript\stsi.bas"

That is to say, I am using 32-bit and the console mode.

btw, idk whether you've changed this file since I first downloaded your library, it appears I've got an old version of it!?

Thanks for your time.
Lothar Schirm
Posts: 436
Joined: Sep 28, 2013 15:08
Location: Germany

Re: Simple WinAPI GUI library

Post by Lothar Schirm »

Yes, indeed, I took the code of the the LoadSaveDialog from the FreeBASIC Portal (see URL in the comment of this function) as it is, so the matter with adding Chr(0, 0) seems not to be quite consistent. But I tested your filter and my filter in the comment with WinDialog.bi contained in the latest download (WinGUI11.zip dated october 27, 2016), and LoadSaveDialog works for me with both filters. I use Windows 8.1 and FreeBASIC 1.05.0, 64 bit.
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: Simple WinAPI GUI library

Post by datwill310 »

Lothar Schirm wrote:Yes, indeed, I took the code of the the LoadSaveDialog from the FreeBASIC Portal (see URL in the comment of this function) as it is, so the matter with adding Chr(0, 0) seems not to be quite consistent. But I tested your filter and my filter in the comment with WinDialog.bi contained in the latest download (WinGUI11.zip dated october 27, 2016), and LoadSaveDialog works for me with both filters. I use Windows 8.1 and FreeBASIC 1.05.0, 64 bit.
Thanks for your reply.

I have downloaded the latest version of WinDialogs.bi through the portal.

Unfortunately, I still can't get the filters to work properly :(!

I use Windows 10 and have tried both 32-bit and 64-bit to no avail.

This is what happens:

Code: Select all

There is only one filter option.
It has the text: StoryScript (*.sts)*.stsAll Files*.*
That is, with my filter parameter:
"StoryScript (*.sts)"+chr(0)+"*.sts"+chr(0)+"All Files"+chr(0)+"*.*"
I have also tried to manually terminate the parameter with chr(0, 0).
As far as I'm aware, nothing is actually filtered in the file explorer: every item type is displayed.
Could this be some sort of error with my system or some weird system option?
Lothar Schirm
Posts: 436
Joined: Sep 28, 2013 15:08
Location: Germany

Re: Simple WinAPI GUI library

Post by Lothar Schirm »

This is my code:

Code: Select all

#Include "WinDialogs.bi"

Dim As String fil, filename

fil = "Basic Files (*.bas)" + Chr(0) + "*.bas" + Chr(0) _
	+ "Text Files (*.txt)" + Chr(0) + "*.txt" + Chr(0)_
	+ "Image Files (*.bmp)" + Chr(0) + "*.bmp" + Chr(0)_
	+ "Executable Files (*.exe)" + Chr(0) + "*.exe" + Chr(0)_
	+ "All Files (*.*)" + Chr(0) + "*.*" + Chr(0, 0)

filename = LoadSaveDialog(, Fil)
Print filename

filename = loadsavedialog(, "StoryScript (*.sts)"+chr(0)+"*.sts"+chr(0)+"All Files"+chr(0)+"*.*")
Print filename

Sleep
It works properly on my system. Using the filter "fil", I get a dialog where I can select all different types of files or all files in my FreeBASIC code directory, and the files are listed according to the desired filter (*.bas, *.txt, *.bmp, *.exe, *.*). Using your filter (*.sts), no files are displayed since I do not have such files. I am sorry, I am afraid I cannot help you. I do not know whether Windows 10 behaves different, I cannot test it, I have only Windows 8.1. Perhaps somebody else using Windows 10 can give support?
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: Simple WinAPI GUI library

Post by datwill310 »

Lothar Schirm wrote:This is my code:

Code: Select all

#Include "WinDialogs.bi"

Dim As String fil, filename

fil = "Basic Files (*.bas)" + Chr(0) + "*.bas" + Chr(0) _
	+ "Text Files (*.txt)" + Chr(0) + "*.txt" + Chr(0)_
	+ "Image Files (*.bmp)" + Chr(0) + "*.bmp" + Chr(0)_
	+ "Executable Files (*.exe)" + Chr(0) + "*.exe" + Chr(0)_
	+ "All Files (*.*)" + Chr(0) + "*.*" + Chr(0, 0)

filename = LoadSaveDialog(, Fil)
Print filename

filename = loadsavedialog(, "StoryScript (*.sts)"+chr(0)+"*.sts"+chr(0)+"All Files"+chr(0)+"*.*")
Print filename

Sleep
It works properly on my system. Using the filter "fil", I get a dialog where I can select all different types of files or all files in my FreeBASIC code directory, and the files are listed according to the desired filter (*.bas, *.txt, *.bmp, *.exe, *.*). Using your filter (*.sts), no files are displayed since I do not have such files. I am sorry, I am afraid I cannot help you. I do not know whether Windows 10 behaves different, I cannot test it, I have only Windows 8.1. Perhaps somebody else using Windows 10 can give support?
Thanks for your reply though, it's helped me notice something.

Perhaps I need to put the filter parameter into one variable and pass that variable instead of the direct expression? It is the only difference between our code, so I'll give that a try once I have a chance to get on my computer.

Thanks for your help.

--EDIT--

:( This did not work.

I have opened other programs and their dialogs have working filters, so maybe it is not to do with my system after all...

But what's really odd is that if I use the default filter option, it works fine...

Something else odd: when I pass in the default filter as a parameter, that does not work, but if I use it implicitly (i.e. without passing a parameter) it works...

I've even copied your example and run it, the same problem occurs...

--EDIT--

I've replaced the default parameter with mine, and it works...
This is particularly strange...
Pim Scheffers
Posts: 54
Joined: Jun 29, 2014 17:15

Re: Simple WinAPI GUI library

Post by Pim Scheffers »

Hey,

First of I would like thank the creator for this nice library.
Later when using the library I realized that it would be nice if we could also put freebasic image buffers onto a window.
I already compiled a subroutine of code (from various code snippets from the forum) that gets the job done, however the image partially disappears when the window is resized to overlap the image.
The covered part of the image is erased if the window is resized to it's original size.

Can somebody help to perfect this function/sub?

greets, Pim

Code: Select all

'=============================================================================================

sub draw_buffer(x as integer, y as integer, source_image as fb.Image ptr, dest_hwnd as HWND)
    if source_image = 0 then
        exit sub
    end if

    dim as BITMAPV4HEADER bmi
    dim as RECT dest_rect
    dim as integer dest_w, dest_h, src_w, src_h
    
    with bmi
        .bV4Size = Len(BITMAPV4HEADER)
        .bv4width = source_image->Pitch shr 2
        .bv4height = -(source_image->Height)
        .bv4planes = 1
        .bv4bitcount = 32
        .bv4v4compression = 0
        .bv4sizeimage = ((source_image->Pitch shr 2) * source_image->Height) shl 2
        .bV4RedMask = &h0f00
        .bV4GreenMask = &h00f0
        .bV4BlueMask = &h000f
        .bV4AlphaMask = &hf000
    end With
    
    var hdc = GetDC(dest_hwnd)
    GetClientRect(dest_hwnd , @dest_rect)
    
    if dest_rect.Bottom > source_image->Height Then
        src_h = source_image->Height       
    else
        src_h = dest_rect.Bottom
    end if
    dest_h = src_h
    
    if dest_rect.right > source_image->Width Then
        src_w = source_image->Width       
    else
        src_w = dest_rect.Right
    end if
    dest_w = src_w
    
    StretchDIBits(hDC, _
                  x, _
                  y, _
                  dest_w, _
                  dest_h, _
                  0, _
                  0, _
                  src_w, _
                  src_h, _
                  cptr(any ptr, source_image) + sizeof(fb.Image), _
                  cptr(BITMAPINFO ptr, @bmi), _
                  DIB_RGB_COLORS, _
                  SRCCOPY)
    DeleteDC(hdc)
end sub
Provoni
Posts: 513
Joined: Jan 05, 2014 12:33
Location: Belgium

Re: Simple WinAPI GUI library

Post by Provoni »

Here is a small change to WinDialogs.bi so that you can set the name of the LoadSaveDialog Window.

Example useage: file_name=loadsavedialog(0,"Open file",filter)

Code: Select all

'===============================================================================
' WinDialogs.bi
' Common Dialogs for Windows
' Created on 20.04.2015
' Last changes on 13/05/2016 
- 13/04/2017: windowname option added by Provoni
'===============================================================================

#Include Once "windows.bi"
#Include Once "win\commdlg.bi"

Function LoadSaveDialog(ByVal savedlog As Long = 0, _
	Byval windowname as string ="", _
	ByVal filter As String = "", _
	ByVal fltrindex As Long = 1, _
	ByVal initdir As String = "", _
	ByVal strDefExt As String = "") As String


	'Windows dialog to choose the drive/path/file name to open or save a file
	'by Volta
	'http://www.freebasic-portal.de/code-beispiele/dateien-laufwerke/dialog-datei-oeffnen-speichern-24.html

	'Parameters:
	'------------------
	'- savedlog = 0: "Open file", 1(<>0): "Save file"
	'- windowname = "": The window name of the dialog shown in the upper left corner
	'- filter = "": "All Files", otherwise a filter according to example "fil" below
	'- fltrindex = 1, otherwise the index of the desired entry in the filter, beginning from 1
	'  (see example "fil" below)
	'- initdir = "" = ".": Current path, otherwise specified path
	'- strDefExt = "": Default extension (appended to the filename if the user fails
	'  to select an extension)
	
	'Example for a filter:
	'---------------------
	'Dim As String fil
	'fil = "Basic Files (*.bas)" + Chr(0) + "*.bas" + Chr(0) _
  '  + "Text Files (*.txt)" + Chr(0) + "*.txt" + Chr(0)_
  '  + "Image Files (*.bmp)" + Chr(0) + "*.bmp" + Chr(0)_
  '  + "Executable Files (*.exe)" + Chr(0) + "*.exe" + Chr(0)_
  '  + "All Files (*.*)" + Chr(0) + "*.*" + Chr(0, 0)
  
  'Examples:
  '---------
  
  'Dim As String FileName
  
	'Open a file without filter (easiest method):
	'FileName = LoadSaveDialog
	
	'Open a file with filter:
	'FileNameName = LoadSaveDialog (,fil)
	
	'Open a file with filter, index 2 (TXT):
	'FileName = LoadSaveDialog (,fil,2)
	
	'Open a file in path "c:\":
	'FileName = LoadSaveDialog (,,,"c:\")
	
	'Save a file:
	'DateiName = LoadSaveDialog (1)
	
	'Save a file with default extension "bak" if no extension has been defined:
	'FileName = LoadSaveDialog (1,,,,"bak")
    
   Dim FB_OFN AS OPENFILENAME
   FB_OFN.lStructSize = Len(FB_OFN)
   FB_OFN.hwndOwner = 0
   FB_OFN.hInstance = 0

   Dim strFilter As String
   If filter = "" Then
      strFilter = "All Files (*.*)" + Chr(0) +"*.*" + Chr(0, 0) 'default
   Else
      strFilter = filter + Chr(0, 0)
   End If
   FB_OFN.lpstrFilter = StrPtr(strFilter)
   FB_OFN.nFilterIndex = fltrindex

   Dim strFile As String *2048
   strFile = Space(2047) + Chr(0)
   FB_OFN.lpstrFile = StrPtr(strFile)
   FB_OFN.nMaxFile = Len(strFile)

   Dim strFileTitle As String *2048
   strFileTitle = String(2048, 0)
   FB_OFN.lpstrFileTitle = StrPtr(strFileTitle)
   FB_OFN.nMaxFileTitle = Len(strFileTitle)

   Dim strdrstr As String
   If initdir = "" Then
      strdrstr = "."     'actual path
   Else
      strdrstr = initdir
   End If
   FB_OFN.lpstrInitialDir = StrPtr(strdrstr)

   Dim strcapt As String
   If savedlog Then
	if windowname="" then windowname="Save File"
      strcapt = windowname '"Save File"
      FB_OFN.lpstrTitle = StrPtr(strcapt)
      If strDefExt > "" Then
         Dim strdext As String
         strdext = strDefExt
         FB_OFN.lpstrDefExt = StrPtr(strdext)
      End If
      FB_OFN.flags = OFN_EXPLORER Or OFN_LONGNAMES Or OFN_OVERWRITEPROMPT Or OFN_HIDEREADONLY
      If GetSaveFileName(@FB_OFN) Then LoadSaveDialog = Trim(strFile)
   Else
	if windowname="" then windowname="Load File"
      strcapt = windowname '"Open file"
      FB_OFN.lpstrTitle = StrPtr(strcapt)
      FB_OFN.flags = OFN_EXPLORER Or OFN_LONGNAMES Or OFN_CREATEPROMPT Or _
                     OFN_NODEREFERENCELINKS Or OFN_HIDEREADONLY
      If GetOpenFileName(@FB_OFN) Then LoadSaveDialog = Trim(strFile)
   End If
End Function


Function ColorPicker() As ULong
	'Windows dialog to select a color (Colorpicker) 
	'by Sebastian  
	'http://www.freebasic-portal.de/code-beispiele/windows-gui/commondialog-zur-farbauswahl-colorpicker-227.html
	'The selected color is returned in the format BGR
	
	'Example:
	'--------
	'Dim As ULong colour
	'colour = Hex(ColorPicker)
	
	#Define WIN_INCLUDEALL
	
	Dim AS CHOOSECOLOR PTR cc     'common dialog box structure
	DIM AS ULong PTR acrCustClr   'custom colors (16x4 bytes)
	DIM AS HWND hwnd              'owner window
	DIM AS HBRUSH hbrush          'brush handle
	DIM AS ULong rgbCurrent       'initial color selection
	
	rgbCurrent = 0  'default: black
	
	cc = CAllocate(sizeof(CHOOSECOLOR))
	acrCustClr = CAllocate(64)
	
	cc->lStructSize = Cast(ULong,sizeof(CHOOSECOLOR))
	cc->hwndOwner = hwnd
	cc->lpCustColors = CAST(LPDWORD, acrCustClr)
	cc->rgbResult = rgbCurrent
	cc->Flags = CC_FULLOPEN Or CC_RGBINIT
	
	if (ChooseColor(cc) = 1) Then
    hbrush = CreateSolidBrush(cc->rgbResult)
    rgbCurrent = cc->rgbResult
	Else
	  rgbCurrent = 0
	End If
		
	Return rgbCurrent

End Function


Function BGRtoRGB(ByVal colour As ULong) As ULong
   'Converts a BGR color format to RGB
   
   Dim As String BGRString, RGBString
   
   BGRString = Hex(colour, 6)
   RGBString = "&H" + Right(BGRString, 2) + Mid(BGRString, 3, 2) + Left(BGRString, 2)
   
   Return ValUInt(RGBString)  ' corrected: this gives ULong 32 bit (ValULng = ULongInt 64bit)
															' MrSwiss 17/04/2016 http://www.freebasic.net/forum/viewtopic.php?f=8&t=24617
   
End Function
Adam L
Posts: 1
Joined: Oct 11, 2016 19:52
Location: USA

Re: Simple WinAPI GUI library

Post by Adam L »

Provoni wrote:Here is a small change to WinDialogs.bi so that you can set the name of the LoadSaveDialog Window.

Example useage: file_name=loadsavedialog(0,"Open file",filter)
Thank you, and "Thank you" to the Author(s).
Pim Scheffers
Posts: 54
Joined: Jun 29, 2014 17:15

Re: Simple WinAPI GUI library

Post by Pim Scheffers »

Hi,

I have a question about deleting controls.
I have (like in many of the examples given) a global HWND variable to a control.

When I click on a button I call a sub (see the code below) to delete the control and after this I re-paint the window and this effectively removes the control.
Then I assign a new control to the same global pointer (this works fine) however this did not release the GDI object (I can see the count steadily climbing in task-manager each time I press the buttton).

Code: Select all

sub destroy_item(hwnd as HWND)
    DestroyWindow(hwnd)
end sub
Can somebody help me to properly destroy a control and reuse the global pointer?
(I ask this because changing the global pointer part of my program would be a lot of work).

Thanks,
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Simple WinAPI GUI library

Post by MrSwiss »

Something like below, maybe ...

Code: Select all

Sub Destroy_Ptr(ByRef hwnd as HWND)
    Deallocate(hwnd)  ' release mem
    hwnd = 0  ' reset ptr (mark it as unused)
End Sub
However, a doubtful process, to start with.
(avoid, whenever possible, "Shared" (aka: Global) variable's/pointer's ...)
If you have to use "shared" then, mainly/only for "Top-Level" handles, like MAIN-WINDOW.
Because: this handle has to be kept, anyway, until destruction (prog. end).
Post Reply