Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - mpgcan

Pages: [1] 2
1
QB64 Discussion / Re: How to remove title Bar from graphics screen?
« on: November 01, 2021, 04:50:13 am »
I have looked at removing borders and I offer my solution on this problem the following works on Windows 8.1

Code: QB64: [Select]
  1. Do: Loop Until _ScreenExists 'run before using _WindowHandle or _title
  2. '####################################################
  3. '# Name:     no_border_no_caption.bas
  4. '# Author:   MPG
  5. '# Purpose:  Remove border and caption. Remaing area
  6. '#           is all client.
  7. '#           Items commented out may be required.
  8. '#           Do: Loop Until _ScreenExists required
  9. '#           on Windows 8.1
  10. '# Revision: November 1 2021 - initial version
  11. '####################################################
  12.  
  13.     Function FindWindow& (ByVal ClassName As _Offset, WindowName$)
  14.  
  15.     Function GetWindowLongA& (ByVal hWnd As _Offset, Byval nIndex As Long)
  16.     Function SetWindowLongA& (ByVal hWnd As _Offset, Byval nIndex As Long, Byval dwNewLong As Long)
  17.     Function SetWindowPos& (ByVal hWnd As _Offset, Byval hWndInsertAfter As Long, Byval x As Long, Byval y As Long, Byval cx As Long, Byval cy As Long, Byval wFlags As Long)
  18.     '    Function ShowScrollBar& (ByVal hWnd As _Offset, Byval wBar As Long, Byval bShow As Long)
  19.  
  20. Const GWL_STYLE = -16
  21. Const WS_BORDER = &H800000
  22. Const WS_CAPTION = &H00C00000
  23. Const WS_THICKFRAME = &H00040000
  24. Const WS_MINIMIZEBOX = &H00020000
  25. Const WS_MAXIMIZEBOX = &H00010000
  26. Const WS_SYSMENU = &H00080000
  27. 'Const SB_BOTH = 3
  28.  
  29. Dim As Long winstyle, Style, a
  30.  
  31. winstyle = GetWindowLongA(hwnd, GWL_STYLE)
  32. Style = (WS_CAPTION Or WS_THICKFRAME Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX Or WS_SYSMENU)
  33. a = SetWindowLongA&(hwnd, GWL_STYLE, winstyle And Not Style)
  34. 'a = ShowScrollBar(hwnd, SB_BOTH, false)
  35.  
  36.  
  37. Screen _NewImage(640, 320, 32)
  38. 'Cls
  39. Line (0, 0)-(639, 319), &HFF00FF00~&&
  40. Line (300, 0)-(300, 320), &HFF00FF00~&&
  41. Line (0, 150)-(640, 150), &HFF00FF00~&&
  42.  
  43. Line (639, 0)-(639, 100), &HFF00FF00~&&
  44. Line (0, 0)-(0, 100), &HFF00FF00~&&
  45.  
  46. Line (400, 0)-(500, 0), &HFF00FF00~&&
  47. Line (400, 319)-(500, 319), &HFF00FF00~&&
  48.  
  49.  
  50. _PrintString (100, 100), "Press any key to end...": Sleep
  51. Print "The end Note:Location"
  52.  

With the do-loop enabled. Shows borders and caption removed .
  [ You are not allowed to view this attachment ]  

All the best.



2
QB64 Discussion / Re: InputBox
« on: October 31, 2021, 05:21:22 am »
One small refinement. In file input_box2.BM locate this section:
Code: QB64: [Select]
  1.     '---Get user input string
  2.     ipb_UserInput '              Run UserInput, data entered saved in buffer ipb.buf
  3.     InputBoxM = ipb_get_string ' Extract data from ipb.buf return string
  4.  
Add the line as shown below:
Code: QB64: [Select]
  1.     '---Get user input string
  2.     ipb_UserInput '              Run UserInput, data entered saved in buffer ipb.buf
  3.     ipb.default_input_text = "" 'Reset inital value after user input
  4.     InputBoxM = ipb_get_string ' Extract data from ipb.buf return string
  5.  
Set the initial value as required automatically resets after user input.
I have included all the files in input_box2.7z

All the best
  [ You are not allowed to view this attachment ]  

3
QB64 Discussion / Re: InputBox
« on: October 30, 2021, 01:55:20 pm »
 It is possible enter a default value in the inputbox.
 I have added variable ipb.default_input_text = "some text"
 The value remembered between inputs hence set it to "" if not required.

input_box_example2.bas
Code: QB64: [Select]
  1. $VersionInfo:Comments=This uses Subclassing Controls!
  2.  
  3. '$Include:'input_box2.BI'
  4.  
  5. '===Your program START ==========
  6. Screen _NewImage(400, 300, 32) '             Set main screen size
  7. Color _RGB(0, 0, 0), _RGB32(205, 238, 205) ' Set colors
  8. _Title "Main Program" ' Set your main program title
  9.  
  10. 'Examples:
  11.  
  12. 'Accepts alpha-numeric characters
  13. Print "=1a= " + InputBoxM("", "", "", "", "")
  14. Print "=1b= " + InputBox
  15.  
  16.  
  17. 'Allows alpha-numeric and extra valid characters.
  18. ipb.default_input_text = "Test 123" 'Note set before displaying input box
  19. Print "=2a= " + InputBoxM("Any character:", "All A+", "", "A+", "")
  20.  
  21. ipb.default_input_text = "" 'Note reset inital value when not required
  22. Print "=2b= " + InputBoxA("Any character:", "All A+")
  23.  
  24. 'Only numeric characters allowed
  25. 'Print "=3a= " + InputBoxM("Digits 0-9 only", "NUMERIC", "", "N", "")
  26. 'Print "=3b= " + InputBoxN("Digits 0-9 only", "NUMERIC")
  27.  
  28. 'Password entry. Display asterisk
  29. 'Print "=4a= " + InputBoxM("Asterisk mask:", "PASSWORD 1", "", "", "A")
  30. 'Print "=4b= " + InputBoxP("Asterisk mask:", "PASSWORD 1")
  31.  
  32. 'Password entry. Display bullet
  33. 'Print "=5a= " + InputBoxM("Bullet mask:", "PASSWORD 2", "", "", "B")
  34. 'Print "=5b= " + InputBoxPB("Bullet mask:", "PASSWORD 2")
  35.  
  36.  
  37. 'Print "=7= " + InputBoxM("Limit 4 characters:", "LIMIT", "4", "", "") '
  38. 'Print "=8= " + InputBoxM("Digits 0-9 and associated characters", "NUMERIC+", "", "N+", "")
  39.  
  40. Print "End"
  41. '===Your program END ============
  42.  
  43. '$Include:'input_box2.BM'
  44.  

input_box2.BI
Code: QB64: [Select]
  1. '###_start_BI_inputbox
  2. Do: Loop Until _ScreenExists 'run before using _WindowHandle or _title
  3. $If 64BIT Then
  4.     $If VERSION < 1.6 Then
  5.         $ERROR Requires Windows QB64 version 1.6 or above
  6.     $End If
  7.  
  8. $If 32BIT Then
  9.     $If VERSION < 1.5 Then
  10.         $ERROR Requires Windows QB64 version 1.5 or above
  11.     $End If
  12.  
  13. '===================================================================
  14. 'Input box for QB64 32 & 64 bit.
  15. 'The QB64 InputBoxM function displays a pop-up dialog box,
  16. 'prompting the user for input. It has OK and Cancel buttons.
  17. 'Function returns a text string containing the user's input
  18. 'when OK button clicked. Returns an empty text string when
  19. 'Cancel button is clicked.
  20. '
  21. ' mpg_input_box_1.bas
  22. ' MPG 9-10-2021
  23. '====================================================================
  24. 'InputBoxM function:
  25. 'InputBoxM (prompt$,title$,length$,numeric$,pwMask$)
  26. '
  27. 'prompt$  - text displayed above the edit control to prompt user e.g. "Please enter a number:".
  28. 'title$   - text displayed in the title bar of the InputBoxM.
  29. 'length$  - maximum number of characters a user allowed to enter.
  30. 'numeri$c - select numeric input. Options are:
  31. '            ""   Default, allows alpha-numeric characters.
  32. '            "A+" Allows alpha-numeric and extra valid characters.
  33. '            "N"   Numeric digits 0-9 only
  34. '            "N+"  Numeric digits 0-9 and associated characters.
  35. 'pwMask$  - select a password mask' Options are:
  36. '            ""  Default no mask
  37. '            "A" Password mask Asterisk
  38. '            "B" Password mask Bullet
  39. '
  40. ' Note1: All variables are optional. Unused variables use a null string.
  41. ' Note2: Pressing cancel button returns a null string e.g ""
  42. ' Note3: You can change default values e.g valid characters, length etc
  43. '        Defaults, located in "Sub inputbox_init" or "Function InputBoxM"
  44. '----------------------------------------------------------------------
  45. 'Predefined functions:
  46. 'Based on the above, five predefined InputBox functions are
  47. 'included as follows:
  48. '
  49. 'InputBox                    - Accepts alpha-numeric characters
  50. 'InputBoxA(prompt$, title$)  - Accepts any character input
  51. 'InputBoxN(prompt$, title$)  - Only numeric characters allowed
  52. 'InputBoxP(prompt$, title$)  - Password entry. Display asterisk
  53. 'InputBoxPB(prompt$, title$) - Password entry. Display bullet
  54. '
  55. ' Note1: Variables are optional. Unused variables use a null string
  56. '----------------------------------------------------------------------
  57. ' VB Inputbox has some limitations as does the edit control. This QB64
  58. ' input box addresses these limitation.
  59. ' 1) Default character length 0x7FFE to 0x7FFFFFFE os dependent.
  60. '    Added option to limit number of characters.
  61. ' 2) Default password mask was an asterisk. Added option to select
  62. '    asterisk or bullet.
  63. ' 3) Numeric characters limited to digits 0-9 added option to have
  64. '    extra associated characters e.g calculator +-%= etc.
  65. '
  66. ' Using subclassing added the following:
  67. ' 4) Disabled context menu (Mouse Right click) copy and paste .
  68. ' 5) Disabled copy and paste using  Ctrl+c Ctrl+v.
  69. ' 6) Disabled copy and paste using Ctrl+Shift+c Ctrl+Shift+v.
  70. ' 7) Disabled annoying beep when pressing enter key.
  71. ' 8) Character validation.
  72. ' 9) Invalid character user alert. Uses MessageBeep.
  73. '
  74. '----------------------------------------------------------------------
  75. ' Code based on ideas from the following references:
  76. ' 1) Windows buttons for 32 and 64 bit IDE
  77. '    https://www.qb64.org/forum/index.php?topic=3217.msg124966#msg124966
  78. ' 2) Base64 Encoding/Decoding with Windows, Mac, and Linux
  79. '    https://www.qb64.org/forum/index.php?topic=3214.msg124919#msg124919
  80. ' 3) Threading
  81. '    https://www.qb64.org/forum/index.php?topic=3865.msg132124#msg132124
  82.  
  83.  
  84. '=======================================================================
  85. '
  86. '-----------------------------------------------------------------------
  87. 'NOTE:
  88. 'Create a new file input_box_WIN.h with the following content (Remove the comments '):
  89. '---Start of file contents:---
  90.      
  91. 'ptrszint FUNC_WINDOWPROC(ptrszint*_FUNC_WINDOWPROC_OFFSET_HWND,uint32*_FUNC_WINDOWPROC_ULONG_UMSG,uptrszint*_FUNC_WINDOWPROC_UOFFSET_WPARAM,ptrszint*_FUNC_WINDOWPROC_OFFSET_LPARAM);
  92. 'LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  93. ' return FUNC_WINDOWPROC((ptrszint *) (& hwnd), & uMsg, & wParam, (ptrszint *) (& lParam));
  94. '}
  95. 'void * GetWindowProc() {
  96. ' return (void *) WindowProc;
  97. '}
  98.      
  99. 'ptrszint FUNC_SUBEDIT(ptrszint*_FUNC_SUBEDIT_OFFSET_HWND,uint32*_FUNC_SUBEDIT_ULONG_UMSG,uptrszint*_FUNC_SUBEDIT_UOFFSET_WPARAM,ptrszint*_FUNC_SUBEDIT_OFFSET_LPARAM);
  100. 'LRESULT CALLBACK SubEdit(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  101. ' return FUNC_SUBEDIT((ptrszint *) (& hwnd), & uMsg, & wParam, (ptrszint *) (& lParam));
  102. '}
  103. 'void * GetSubEdit() {
  104. ' return (void *) SubEdit;
  105. '}
  106.      
  107. '---End of file contents---
  108. 'Input box uses the input_box_WIN.h file to get the WindowProc and SubEdit . Note: Place above file in your working folder (The QB64 folder).
  109. '----------------------------------------------------------------
  110.      
  111. '==Note: InputBox requires this section to be added to your program.==========
  112. 'Creates a global variable ipb. Its corresponding elements, are also global.
  113. Dim Shared ipb As input_box_udt 'The input_box_udt user defined type
  114. inputbox_init '                  Define ipb structure and initialize elements
  115.      
  116. '*****Subclassing
  117. Dim Shared OldWindowProc As Long 'Global variable store old windows process
  118. '*****End Subclassing
  119.  
  120. '###_end_BI_inputbox
  121.  

input_box2.BM

Code: QB64: [Select]
  1. '###_start_BM_inputbox
  2. '######--INPUT BOX FUNCTIONS and SUBS--######################################
  3.  
  4. '--inputbox_init:  Creates a user defined type. This type is used to create
  5. '                  global variable ipb. Its corresponding elements are
  6. '                  global. Some variables are initialised in this function.
  7.  
  8. Sub inputbox_init
  9.     Const FALSE = 0
  10.     Const TRUE = Not FALSE
  11.  
  12.     Type input_box_udt
  13.         buf As String * 64 '  Buffer to store entered characters
  14.         hw As _Offset '       Pointer to inputbox window
  15.         hwLabel As _Offset '  Pointer to label
  16.         hwb0 As _Offset '     Pointer button 0 - OK
  17.         hwb1 As _Offset '     Pointer button 1 - Cancel
  18.         hwe As _Offset '      Pointer to single line edit control
  19.  
  20.         pw_mask As Integer '   Enable password mask flag
  21.         pw_bullet As Integer ' Password mask bullet flag
  22.         max_length As Integer 'Maximum allowed characters
  23.  
  24.         caption_text As String 'Window title
  25.         prompt_text As String ' Instructions to user
  26.         valid_str As String '   All allowed characters
  27.  
  28.         button0_text As String ' Left button
  29.         button1_text As String ' Right button
  30.  
  31.         x As Long 'Position of inputbox
  32.         y As Long 'Position of inputbox
  33.         max_char_allowed As Long ' Maximum number of input characters allowed
  34.  
  35.         default_input_text As String ' Display to user initial value
  36.     End Type
  37.  
  38.     '---Set default values
  39.     ipb.button0_text = "OK"
  40.     ipb.button1_text = "Cancel"
  41.  
  42.     '---Center InputBox window
  43.     Dim As Long userwidth, userheight
  44.     userwidth = _DesktopWidth: userheight = _DesktopHeight 'get current screen resolution
  45.  
  46.     ipb.x = (userwidth \ 2 - 358 \ 2) - 3
  47.     ipb.y = (userheight \ 2 - 136 \ 2) - 29
  48.  
  49.     ipb.default_input_text = "" 'Set initial value
  50. '-- END inputbox_init:
  51.  
  52. 'Predefined function 1: - Allow numeric and alpha characters
  53. Function InputBox$ ()
  54.     InputBox = InputBoxM("", "", "", "", "")
  55.  
  56. 'Predefined function 2: - Allows alpha-numeric and extra valid characters.
  57. Function InputBoxA$ (prompt As String, title As String)
  58.     InputBoxA = InputBoxM(prompt, title, "", "A+", "")
  59.  
  60. 'Predefined function 3: - Only numeric characters allowed.
  61. Function InputBoxN$ (prompt As String, title As String)
  62.     InputBoxN = InputBoxM(prompt, title, "", "N", "")
  63.  
  64. 'Predefined function 4: - Password entry. Display asterisk.
  65. Function InputBoxP$ (prompt As String, title As String)
  66.     InputBoxP = InputBoxM(prompt, title, "", "", "A")
  67.  
  68. 'Predefined function 5: - Password entry. Display bullet.
  69. Function InputBoxPB$ (prompt As String, title As String)
  70.     InputBoxPB = InputBoxM(prompt, title, "", "", "B")
  71.  
  72.  
  73.  
  74. '---Main input box
  75. Function InputBoxM$ (prompt As String, title As String, maxLength As String, numeric As String, pwMask As String)
  76.     Const FALSE = 0
  77.     Const TRUE = Not FALSE
  78.     Dim As String str1, str2, str3, str4
  79.  
  80.     '---Set prompt text
  81.     ipb.prompt_text = "Enter some text:" 'Default value
  82.     If prompt <> "" Then
  83.         ipb.prompt_text = prompt 'Label text. User instrutions
  84.     End If
  85.  
  86.     '---Set pop-up window title (caption) text
  87.     ipb.caption_text = "InputBox" 'Default value
  88.     If title <> "" Then
  89.         ipb.caption_text = title 'User pop-up window title
  90.     End If
  91.  
  92.     '--Set maximum number of characters allowed
  93.     ipb.max_length = 40 'Default allowed characters 40
  94.     If maxLength <> "" Then
  95.         ipb.max_length = Val(maxLength) 'Required length
  96.     End If
  97.  
  98.     '---Set allowed characters.
  99.     'numeric: Options are
  100.     '  ""    Default, allows alpha-numeric characters.
  101.     '  "A+"  Allows alpha-numeric and extra valid characters.
  102.     '  "N"   Numeric digits 0-9 only
  103.     '  "N+"  Numeric digits 0-9 and associated characters.
  104.  
  105.     str1 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 'Alpha
  106.     str2 = "0123456789 " ' numeric
  107.     str3 = Chr$(34) + "!$%^&()+{}[]:@#<>?" ' Extra associated alpha/numeric characters
  108.     str4 = "%^.+-*/=" '      Associated numeric characters e.g basic calculator
  109.  
  110.     ipb.valid_str = ""
  111.  
  112.     If numeric = "" Then '                  Set default alpha numeric characters
  113.         ipb.valid_str = str1 + str2 '       Valid alpha/numeric characters
  114.     End If
  115.     If numeric = "A+" Then '                Set allowed alpha numeric and extra characters
  116.         ipb.valid_str = str1 + str2 + str3 'Valid alpha/numeric and extra characters
  117.     End If
  118.     If numeric = "N" Then '    Set allowed numeric characters
  119.         ipb.valid_str = str2 ' Valid characters 0-9
  120.     End If
  121.     If numeric = "N+" Then '          Set numeric and associated characters.
  122.         ipb.valid_str = str2 + str4 ' Valid numeric and associated characters
  123.     End If
  124.  
  125.     '---Set mask option
  126.     ' ""  Default no mask
  127.     ' "A" Password mask asterisk
  128.     ' "B" Password mask Bullet
  129.     ipb.pw_mask = FALSE '                  Reset flag, disable password mask
  130.     ipb.pw_bullet = FALSE '                Reset bullet flag
  131.  
  132.     If pwMask = "A" Or pwMask = "B" Then ' Mask required
  133.         ipb.pw_mask = TRUE '               Set flag, mask required
  134.         If pwMask = "B" Then '             Bullet required
  135.             ipb.pw_bullet = TRUE '         Set bullet flag
  136.         End If
  137.     End If
  138.  
  139.     '---Get user input string
  140.     ipb_UserInput '              Run UserInput, data entered saved in buffer ipb.buf
  141.     InputBoxM = ipb_get_string ' Extract data from ipb.buf return string
  142.  
  143. '---Function Extract data from ipb.buf return input string
  144. Function ipb_get_string$ ()
  145.     Dim As String a
  146.  
  147.     'Extract string from buf
  148.     a = _Trim$(ipb.buf) '                  Remove spaces. Buffer contains a null terminated
  149.     a = Left$(a, InStr(a, Chr$(0)) - 1) '  string. Find position of null and extract
  150.     ipb.buf = "" '                         characters upto this null character. Clear buffer
  151.  
  152.     ipb_get_string = a 'Return clean string
  153.      
  154. '===Main Sub ===========================
  155. Sub ipb_UserInput
  156.     '--Constants
  157.     Const FALSE = 0
  158.     Const TRUE = Not FALSE
  159.  
  160.     Const IDC_ARROW = &H7F00
  161.     Const COLOR_WINDOW = 5
  162.      
  163.     Const WS_OVERLAPPED = 0
  164.     Const WS_CAPTION = &H00C00000
  165.     Const WS_SYSMENU = &H00080000
  166.     Const WS_VISIBLE = &H10000000
  167.     Const WS_CHILD = &H40000000
  168.     Const WS_TABSTOP = &H00010000
  169.     Const WS_EX_CLIENTEDGE = &H00000200
  170.     Const BS_PUSHBUTTON = 0
  171.     Const CW_USEDEFAULT = &H80000000
  172.     Const SW_SHOWDEFAULT = &HA
  173.  
  174.     Const ES_LEFT = 0
  175.     Const ES_NUMBER = &H2000
  176.  
  177.     Const WS_OVERLAPPEDWINDOW = WS_OVERLAPPED Or WS_CAPTION
  178.  
  179.     '--Types
  180.     Type POINT
  181.         As Long x
  182.         As Long y
  183.     End Type
  184.  
  185.     Type MSG
  186.         As _Offset hwnd
  187.         As _Unsigned Long message
  188.         As _Unsigned _Offset wParam 'unsigned pointer sized integer
  189.         As _Offset lParam '          pointer sized integer
  190.         As _Unsigned Long time
  191.         As POINT pt
  192.     End Type
  193.  
  194.     Type WNDCLASSA
  195.         As _Unsigned Long style
  196.         $If 64BIT Then
  197.             As String * 4 padding
  198.         $End If
  199.         As _Offset lpfnWndProc
  200.         As Long cbClsExtra, cbWndExtra
  201.         As _Offset hInstance, hIcon, hCursor, hbrBackground, lpszMenuName, lpszClassName
  202.     End Type
  203.  
  204.     '--Libaries
  205.  
  206.    
  207.     Declare Library "input_box_WIN"
  208.         Function GetWindowProc%& () 'Windows procedure address
  209.         '***Subclassing
  210.         Function GetSubEdit%& () '   Edit procedure address
  211.         '***End Subclassing
  212.     End Declare
  213.  
  214.     '***Subclassing
  215.         Function SetWindowLongPtr& Alias "SetWindowLongPtrA" (ByVal hwnd As _Offset, Byval nIndex As Long, Byval dwNewLong As Long)
  216.     End Declare
  217.     '***End Subclassing
  218.  
  219.     '  Declare CustomType Library
  220.     Declare Dynamic Library "user32"
  221.         Function CallWindowProc& Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, Byval hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  222.         Function SendMessageA%& (ByVal hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  223.         Function DefWindowProcA%& (ByVal hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  224.         Sub PostQuitMessage (ByVal nExitCode As Long)
  225.         Function LoadCursorW%& (ByVal hInstance As _Offset, Byval lpCursorName As _Offset)
  226.         Function RegisterClassA~% (ByVal lpWndClass As _Offset)
  227.         Function CreateWindowExA%& (ByVal dwExStyle As Long, Byval lpClassName As _Offset, Byval lpWindowName As _Offset, Byval dwStyle As Long, Byval X As Long, Byval Y As Long, Byval nWidth As Long, Byval nHeight As Long, Byval hWndParent As _Offset, Byval hMenu As _Offset, Byval hInstance As _Offset, Byval lpParam As _Offset)
  228.         Function ShowWindow& (ByVal hWnd As _Offset, Byval nCmdShow As Long)
  229.         Function UpdateWindow& (ByVal hWnd As _Offset)
  230.         Function GetMessageA% (ByVal lpMsg As _Offset, Byval hWnd As _Offset, Byval wMsgFilterMin As _Unsigned Long, Byval wMsgFilterMax As _Unsigned Long)
  231.         Function TranslateMessage& (ByVal lpMsg As _Offset)
  232.         Function DispatchMessageA%& (ByVal lpmsg As _Offset)
  233.         Sub DestroyWindow (ByVal hWnd As _Offset)
  234.         Function PostMessageA%& (ByVal hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  235.         Function SetFocus& (ByVal hWnd As _Offset)
  236.         Function GetWindowLongA& (ByVal hwnd As _Offset, Byval nIndex As Long)
  237.         Function SetWindowPos& (ByVal hWnd As _Offset, Byval hWndInsertAfter As _Offset, Byval X As Integer, Byval Y As Integer, Byval cx As Integer, Byval cy As Integer, Byval uFlags As _Offset)
  238.         Function SendMessageW%& (ByVal hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  239.         '     Function SetWindowLongA& (ByVal hwnd As _Offset, Byval nIndex As Long, Byval dwNewLong As Long)
  240.         Sub MessageBeep (ByVal alert As _Unsigned Long)
  241.     End Declare
  242.  
  243.     Declare Dynamic Library "kernel32"
  244.         Function GetModuleHandleA%& (ByVal lpModuleName%&)
  245.         Function GetLastError~& ()
  246.     End Declare
  247.     '--End Libaries
  248.  
  249.  
  250.     '--Variables
  251.     Static registered As Integer 'Variables initialized to 0 (false) hence not registered. Value retained between functtion calls
  252.  
  253.     Dim hi As _Offset '   Handle to application instance
  254.     Dim wc As WNDCLASSA ' define wc as WNDCLASSEX structure
  255.     Dim msg As MSG
  256.  
  257.     Dim dummyL As Long '   Dummy variable
  258.     Dim dummyO As _Offset 'Dummy variable
  259.     Dim t0 As String '       Type of control
  260.     Dim t1 As String '       Title or controls text
  261.  
  262.     Dim MainClassName As String * 5
  263.     MainClassName = "main" + Chr$(0)
  264.  
  265.     Dim CrLf As String * 2 '     define as 2 byte STRING
  266.     CrLf = Chr$(13) + Chr$(10) ' carriage return and line feed
  267.  
  268.     Dim As String className '               Variable className stores name of our window class
  269.     className = "myWindowClass" + Chr$(0) ' Used in wc. which in turn is used to register window class with the system.
  270.  
  271.     hi = GetModuleHandleA(0) 'Handle to application instance
  272.  
  273.     '---Step 1: Registering the Window Class
  274.     'Fill out the members of WNDCLASSEX structure (wc) and call RegisterClassA
  275.  
  276.     wc.style = 0 '                            Class Styles (CS_*), not Window Styles (WS_*) This is usually be set to 0.
  277.     wc.lpfnWndProc = GetWindowProc '          Pointer to the window procedure for this window class. (see WIN.h)
  278.     wc.cbClsExtra = 0 '                       Amount of extra data allocated for this class in memory. Usually 0.
  279.     wc.cbWndExtra = 0 '                       Amount of extra data allocated in memory per window of this type. Usually 0.
  280.     wc.hInstance = hi '                       Handle to application instance .
  281.     wc.hIcon = 0 '                            Large (usually 32x32) icon shown when the user presses Alt+Tab. Set to 0
  282.     wc.hCursor = LoadCursorW(0, IDC_ARROW) '  Cursor that will be displayed over our window.
  283.     wc.hbrBackground = COLOR_WINDOW 'was +1   Background Brush to set the color of our window. '
  284.     wc.lpszMenuName = 0 '                     Name of a menu resource to use for the windows with this class.
  285.     wc.lpszClassName = _Offset(className) '   Name to identify the class with.
  286.  
  287.     If Not registered Then '   First time in funcion OK to register.
  288.         If RegisterClassA(_Offset(wc)) = 0 Then
  289.             Print "RegisterClassA failed:"; GetLastError
  290.             End
  291.         End If
  292.         registered = TRUE ' Class was registered
  293.     End If
  294.  
  295.     '--Step 2: Creating the Windows
  296.     'After registering the class, create a window with it using CreateWindowExA.
  297.  
  298.     'Note: A visible un-owned window gets a taskbar button. To hide the inputbox window taskbar button
  299.     'make the inputbox owned by our main applicationusing using  _WindowHandle instead of 0'
  300.     t1 = ipb.caption_text + Chr$(0) 'Window title
  301.     ipb.hw = CreateWindowExA(0, _Offset(className), _Offset(t1), WS_OVERLAPPEDWINDOW, ipb.x, ipb.y, 358, 130, _WindowHandle, 0, hi, 0): If 0 = ipb.hw Then System
  302.  
  303.     'Controls are just child windows. They have a procedure, a class etc... that is registered by the system.
  304.  
  305.     'Label
  306.     t0 = "STATIC" + Chr$(0) '        Window control is STATIC predefined class
  307.     t1 = ipb.prompt_text + Chr$(0) ' Label text
  308.     ipb.hwLabel = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_VISIBLE Or WS_CHILD, 9, 5, 372, 16, ipb.hw, 0, hi, 0): If 0 = ipb.hwLabel Then System
  309.  
  310.  
  311.     'OK Button 0
  312.     t0 = "BUTTON" + Chr$(0) '   Window control is BUTTON predefined class
  313.     t1 = ipb.button0_text + Chr$(0)
  314.     ipb.hwb0 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_TABSTOP Or WS_VISIBLE Or WS_CHILD Or BS_PUSHBUTTON, 175, 65, 80, 23, ipb.hw, 0, hi, 0): If 0 = ipb.hwb0 Then System
  315.  
  316.     'Cancel button 1
  317.     t1 = ipb.button1_text + Chr$(0)
  318.     ipb.hwb1 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_TABSTOP Or WS_VISIBLE Or WS_CHILD Or BS_PUSHBUTTON, 262, 65, 80, 23, ipb.hw, 0, hi, 0): If 0 = ipb.hwb1 Then System
  319.  
  320.     'Edit control
  321.     t0 = "EDIT" + Chr$(0)
  322.     '    t1 = "This is a edit control." + Chr$(0)
  323.     t1 = "" + Chr$(0)
  324.     ipb.hwe = CreateWindowExA(WS_EX_CLIENTEDGE, _Offset(t0), _Offset(t1), WS_VISIBLE Or WS_CHILD Or ES_LEFT, 12, 30, 330, 26, ipb.hw, 0, hi, 0): If 0 = ipb.hwe Then System
  325.  
  326.     '===Write default text to edit control and set cursor pos
  327.     Const WM_SETTEXT = &H000C
  328.     Const EM_SETSEL = &HB1
  329.     Dim ipbLen As Integer
  330.     If ipb.default_input_text <> "" Then 'Empty skip this
  331.         t0 = ipb.default_input_text + Chr$(0) 'Text to send to Edit control
  332.         dummyO = SendMessageA(ipb.hwe, WM_SETTEXT, 0, _Offset(t0)) 'Set control text
  333.         ipbLen = Len(ipb.default_input_text) '                      Length of string
  334.         dummyO = SendMessageA(ipb.hwe, EM_SETSEL, ipbLen, ipbLen) ' Set cursor to end of text
  335.     End If
  336.  
  337.  
  338.     '---Set character length
  339.     Const EM_LIMITTEXT = &H00C5
  340.     dummyO = SendMessageA(ipb.hwe, EM_LIMITTEXT, ipb.max_length, 0) 'Send message maxcharacters 8
  341.  
  342.     '----Enable and configure password mask.
  343.     'Note: The bullet is Unicode (9679 or 0x25CF ) use  SendMessageW. Use SendMessageA for old Asterisk (42)
  344.     Const EM_SETPASSWORDCHAR = &HCC
  345.     If ipb.pw_mask Then 'Input Mask required
  346.         If ipb.pw_bullet Then 'Set bullet
  347.             dummyO = SendMessageW(ipb.hwe, EM_SETPASSWORDCHAR, 9679, 0) 'Set bullet password mask
  348.         Else 'Standard *
  349.             dummyO = SendMessageA(ipb.hwe, EM_SETPASSWORDCHAR, 42, 0) 'Set Asterisk default mask
  350.         End If
  351.     Else 'Mask not required
  352.         dummyO = SendMessageA(ipb.hwe, EM_SETPASSWORDCHAR, 0, 0) '  Turn password mask off
  353.         ' dummyO = SendMessageW(ipb.hwe, EM_SETPASSWORDCHAR, 0, 0) '   Turn password mask off
  354.     End If
  355.  
  356.     '*****Subclassing
  357.     Const GWLP_WNDPROC = -4 ' Sets a new address for the window procedure
  358.     OldWindowProc = SetWindowLongPtr(ipb.hwe, GWLP_WNDPROC, ConvertOffset(GetSubEdit)) ' set your custom procedure
  359.     '*****End Subclassing
  360.  
  361.     'Display and Update window to ensure it has properly redrawn itself on the screen.
  362.     dummyL = ShowWindow(ipb.hw, SW_SHOWDEFAULT)
  363.     dummyL = UpdateWindow(ipb.hw)
  364.  
  365.     ' Force window to top and select with screen click
  366.     Const HWND_TOPMOST = -1 '      window above all others no focus unless active
  367.     Const SWP_NOSIZE = &H0001 '    ignores cx and cy size parameters
  368.     Const SWP_NOACTIVATE = &H0010 'does not activate window
  369.     dummyL = SetWindowPos(ipb.hw, HWND_TOPMOST, ipb.x, ipb.y, 0, 0, SWP_NOSIZE Or SWP_NOACTIVATE) 'force to top
  370.     _ScreenClick ipb.x + 160, ipb.y + 96 'Force focus and move cursor to left of ok button
  371.  
  372.     '-- Step 3: The Message Loop
  373.     While GetMessageA(_Offset(msg), 0, 0, 0) > 0 ' gets a message from our application's message queue.
  374.         dummyL = TranslateMessage(_Offset(msg)) '  performs some additional processing on keyboard events
  375.         dummyO = DispatchMessageA(_Offset(msg)) '  sends the message out to the window that the message was sent to
  376.     Wend
  377. '===End main function ===========================
  378.      
  379.      
  380. '-- Step 4: the Window Procedure
  381. Function WindowProc%& (hWnd As _Offset, uMsg As _Unsigned Long, wParam As _Unsigned _Offset, lParam As _Offset)
  382.     Const WM_CREATE = &H0001
  383.     Const WM_CLOSE = &H0010
  384.     Const WM_DESTROY = 2
  385.     Const WM_COMMAND = &H0111
  386.     Const BN_CLICKED = 0
  387.     Const WM_GETTEXT = &H000D
  388.     Const WM_SETFOCUS = &H0007
  389.     Dim dummyO As _Offset 'Dummy variable
  390.     Dim dummyL As Long '   Dummy variable
  391.  
  392.     Select Case uMsg
  393.  
  394.         Case WM_CLOSE
  395.             DestroyWindow (hWnd) 'Destroy window and child windows
  396.             WindowProc = 0
  397.  
  398.         Case WM_DESTROY
  399.             PostQuitMessage 0 ' Want to exit the program
  400.             WindowProc = 0
  401.  
  402.         Case WM_SETFOCUS
  403.             dummyL = SetFocus(ipb.hwe) 'Set Edit control focus
  404.             WindowProc = 0
  405.  
  406.         Case WM_COMMAND
  407.             '==============
  408.             If wParam = BN_CLICKED Then
  409.                 Select Case lParam
  410.                     'A button was clicked test each one
  411.                     '---Sandard buttons---
  412.                     Case ipb.hwb0 'OK button
  413.                         'Print "Button 0 pressed OK"
  414.                         'Get input text and copy to buffer (buf)
  415.                         dummyO = SendMessageA(ipb.hwe, WM_GETTEXT, Len(ipb.buf), _Offset(ipb.buf))
  416.                         'Print Len(buf)
  417.                         dummyO = PostMessageA(hWnd, WM_CLOSE, 0, 0) 'Close
  418.                         WindowProc = 0
  419.  
  420.                     Case ipb.hwb1 'Cancel button
  421.                         'Print "Button 1 pressed Cancel"
  422.                         ipb.buf = "" 'reset zero-length string ("").
  423.                         dummyO = PostMessageA(hWnd, WM_CLOSE, 0, 0) 'Close
  424.                         WindowProc = 0
  425.                         '---End standard buttons---
  426.                 End Select
  427.             Else
  428.                 'Not our message send back to system for processing
  429.                 WindowProc = DefWindowProcA(hWnd, uMsg, wParam, lParam)
  430.             End If
  431.             '=================
  432.             WindowProc = 0
  433.  
  434.         Case Else
  435.             'Not our message send back to system for processing
  436.             WindowProc = DefWindowProcA(hWnd, uMsg, wParam, lParam)
  437.     End Select
  438. '######--END INPUT BOX FUNCTIONS and SUBS--##################################
  439.      
  440. 'Ref https://www.qb64.org/forum/index.php?topic=1553.msg108409#msg108409
  441. 'Ref https://www.qb64.org/forum/index.php?topic=2905.msg121660#msg121660
  442.  
  443. Function ConvertOffset&& (value As _Offset)
  444.     Dim m As _MEM 'Define a memblock
  445.     m = _Mem(value) 'Point it to use value
  446.     $If 64BIT Then
  447.         Dim temp As _Integer64
  448.         'On 64 bit OSes, an OFFSET is 8 bytes in size.  We can put it directly into an Integer64
  449.         _MemGet m, m.OFFSET, temp
  450.         ConvertOffset = temp
  451.     $Else
  452.         Dim temp As Long
  453.         'However, on 32 bit OSes, an OFFSET is only 4 bytes.  We need to put it into a LONG variable first
  454.         _MemGet m, m.OFFSET, temp 'Like this
  455.         ConvertOffset = temp 'And then assign that long value to ConvertOffset&&
  456.     $End If
  457.     _MemFree m 'Free the memblock
  458.  
  459. '*****Subclass function
  460. Function SubEdit%& (hWnd As _Offset, uMsg As _Unsigned Long, wParam As _Unsigned _Offset, lParam As _Offset)
  461.     Const FALSE = 0
  462.     Const TRUE = Not FALSE
  463.     Const WM_NCDESTROY = &H82
  464.     Const GWLP_WNDPROC = -4 ' Sets a new address for the window procedure
  465.     Const WM_CONTEXTMENU = 123
  466.     Const WM_CHAR = 258
  467.     Const VK_RETURN = &H000D
  468.     Const BM_CLICK = 245
  469.     Const MB_ICONWARNING = &H30
  470.  
  471.     Dim processed As Integer 'Key valid and processed
  472.     Dim dummyL As Long '      Dummy variable
  473.     Dim dummyO As _Offset '   Dummy variable
  474.     Dim ChrValid As Integer ' Character is valid
  475.     Dim i As Integer
  476.  
  477.     'Set initial condition
  478.     processed = FALSE 'Set initial value. No key processed
  479.  
  480.     'If we're being destroyed, restore the original WindowProc.
  481.     '*****Subclassing
  482.     If uMsg = WM_NCDESTROY Then
  483.         dummyL = SetWindowLongPtr(hWnd, GWLP_WNDPROC, OldWindowProc)
  484.     End If
  485.     '*****End Subclassing
  486.  
  487.     'Disable context menu popup. Prevents a paste operation
  488.     If uMsg = WM_CONTEXTMENU Then
  489.         processed = TRUE '   Key processed nothing elese to do
  490.     End If
  491.  
  492.     'Disable Ctrl+V   Prevents a paste operation
  493.     If uMsg = WM_CHAR And wParam = 22 Then
  494.         processed = TRUE '   Key processed nothing elese to do
  495.     End If
  496.  
  497.     'Disable Enter key. Prevents anoying beep. Force enter to produce OK button click
  498.     'Pressing the enter key with Edit Control  in focus.
  499.     'Default behavior is to produce an annoying beep this is
  500.     'because enter is an invalid key for this control.
  501.  
  502.     If uMsg = WM_CHAR And wParam = VK_RETURN Then 'Enter key pressed
  503.         dummyO = SendMessageA(ipb.hwb0, BM_CLICK, 0, 0) ' Send message (button click) to OK button
  504.         processed = TRUE '   Key processed nothing elese to do
  505.     End If
  506.  
  507.     'Valid character section all others invalid
  508.     If uMsg = WM_CHAR Then 'There is a character to process
  509.         'Print wParam
  510.  
  511.         ChrValid = FALSE '                Set initial value
  512.         For i = 1 To Len(ipb.valid_str) ' Scan valid characters and backspace=8
  513.             If wParam = Asc(Mid$(ipb.valid_str, i, 1)) Or wParam = 8 Then
  514.                 ChrValid = TRUE ' Key in valid range. Allow default processing
  515.             End If
  516.         Next
  517.  
  518.         If Not ChrValid Then ' Invalid character remove by setting processed
  519.             processed = TRUE ' true flag. Forceses return 0 for invalid keys'
  520.             'Alert user.
  521.             If Not (wParam = VK_RETURN) Then ' Note: Return key is valid.
  522.                 MessageBeep MB_ICONWARNING '   For invalid characters
  523.             End If '                           create a "ding" to alert user.
  524.         End If
  525.     End If
  526.     'End valid character
  527.  
  528.     'Set return value
  529.     If processed Then 'A key was processed
  530.         SubEdit = 0 '  Return 0 no further processing required
  531.     Else '             No key processed pass onto default  processing
  532.         '*****Subclassing
  533.         SubEdit = CallWindowProc(OldWindowProc, hWnd, uMsg, wParam, lParam)
  534.         '*****End Subclassing
  535.     End If
  536.  
  537. '*****End Subclass functionn
  538. '###_start_BM_inputbox
  539.  

All the best.




4
QB64 Discussion / Re: How to remove title Bar from graphics screen?
« on: October 30, 2021, 03:30:19 am »
I had a delay problem similar to this, one of you guys provided a neat solution which seems to work on this. At the top of your script add the following line :
Code: QB64: [Select]
  1. Do: Loop Until _ScreenExists 'before using _WindowHandle or _title

Worked on this:
Code: QB64: [Select]
  1. Do: Loop Until _ScreenExists 'before using _WindowHandle or _title
  2.  
  3. Const HWND_TOPMOST%& = -1
  4. Const SWP_NOSIZE%& = &H1
  5. Const SWP_NOMOVE%& = &H2
  6. Const SWP_SHOWWINDOW%& = &H40
  7.  
  8.     Function GetWindowLongA& (ByVal hwnd As Long, Byval nIndex As Long)
  9.     Function SetWindowPos& (ByVal hWnd As Long, Byval hWndInsertAfter As _Offset, Byval X As Integer, Byval Y As Integer, Byval cx As Integer, Byval cy As Integer, Byval uFlags As _Offset)
  10.     Function SetWindowLongA& (ByVal hwnd As Long, Byval nIndex As Long, Byval dwNewLong As Long)
  11.     Function GetForegroundWindow&
  12.     Function SetLayeredWindowAttributes& (ByVal hwnd As Long, Byval crKey As Long, Byval bAlpha As _Unsigned _Byte, Byval dwFlags As Long)
  13. Screen _NewImage(600, 480, 32)
  14. GWL_STYLE = -16
  15. ws_border = &H800000
  16. WS_VISIBLE = &H10000000
  17. _Title "Borderless Window"
  18. Dim hwnd As Long
  19. Level = 175
  20. SetWindowOpacity hwnd, Level
  21.  
  22. winstyle2& = GetWindowLongA&(hwnd, GWL_STYLE)
  23. winstyle& = -12582913
  24. a& = SetWindowLongA&(hwnd, GWL_STYLE, winstyle& And WS_VISIBLE) ' AND NOT WS_VSCROLL) ' AND NOT ws_border)
  25. a& = SetWindowPos&(hwnd, 0, 0, 0, 0, 0, 39)
  26. msg$ = "Welcome to Translucent Windows Without Borders!"
  27. i = 16
  28. Color &HFFFFFFFF, &H0 ' white foreground, transparent background
  29.     _Limit 60
  30.     FGwin& = GetForegroundWindow&
  31.     If hwnd <> FGwin& Then ' QB64 no longer in focus.
  32.         While _MouseInput: Wend
  33.         a& = SetWindowPos&(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE + SWP_SHOWWINDOW)
  34.         Do: _Limit 30: Loop Until hwnd = GetForegroundWindow&
  35.     End If
  36.     If InKey$ = Chr$(27) Then Exit Do
  37.     For y = 480 To 0 Step -1
  38.         For x = 640 To 0 Step -1
  39.             PSet (x, 480 - y), _RGB(y / 2 Mod 256, 100, 200) ' (x MOD 512 XOR y) MOD 256, y MOD 256)
  40.         Next
  41.     Next
  42.     _PrintString (92, 1), msg$
  43.     _PrintString (1, 464), "Press Esc to quit."
  44.     _PrintString (250, i), "Hi Chez-Pete!"
  45.     _Display
  46.     i = i + 1
  47.     If i > 464 Then i = 16
  48.  
  49. Sub SetWindowOpacity (hwnd As Long, Level)
  50.     Dim Msg As Long
  51.     Const G = -20
  52.     Const LWA_ALPHA = &H2
  53.     Const WS_EX_LAYERED = &H80000
  54.     Msg = GetWindowLongA&(hwnd, G)
  55.     Msg = Msg Or WS_EX_LAYERED
  56.     action = SetWindowLongA&(hwnd, G, Msg)
  57.     action = SetLayeredWindowAttributes(hwnd, 0, Level, LWA_ALPHA)
  58.  
All the best.

5
Programs / Re: Windows buttons for 32 and 64 bit IDE - Take 2
« on: October 13, 2021, 06:03:12 am »
RichEdit versions 1.0, 2.0, 3.0 and 4.1 were included in Windows at various times. Not sure which one corresponds to what version of Windows. I used the latest version which may not be appropriate for your requirements. See this page  https://docs.microsoft.com/en-us/windows/win32/controls/about-rich-edit-controls .
Quote
I am not sure why string need to use _OFFSET...is this string pointer or general purpose pointer which just read content from
variable address ..but ok ..

I think the following best explains why they are string pointers:

LPCTSTR lpClassName –pointer to a null-terminated string containing the predefined control-class names.  The class name can either be one created with RegisterClass or one of the predefined classes used to create child controls. However although the lpClassName is declared to be an LPCTSTR it can be either a pointer to a string or a class atom returned by RegisterClass or RegisterClassEx.

LPCTSTR lpWindowName – pointer to a null-terminated string that specifies the window name.

6
Programs / Re: Windows buttons for 32 and 64 bit IDE - Take 2
« on: October 12, 2021, 10:35:33 am »
To get you up and running edit file window_controls_7.bas as follows:
Code: QB64: [Select]
  1.  
  2. '1)--Under Libaries add the following:
  3.  
  4. '2)--under Variables add the following:
  5. Dim Shared hwRe1 As _Offset 'Rich edit control
  6.  
  7. '3)---change this line as shown. Increases window size:
  8. hw = CreateWindowExA(0, _Offset(className), _Offset(t1), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 432, 640, 0, 0, hi, 0): If 0 = hw Then System
  9.  
  10. '4)---A the end of Edit multiline control section
  11. '---add the following section:
  12.  
  13. '5)---Richedit control
  14. t0 = "RICHEDIT50W" + Chr$(0) 'predefined class
  15. t1 = "This is a" + CrLf + "Multiline Richedit control." + CrLf + "Click in me and type." + CrLf + "It should scroll automatically in both directions, but there aren't any scroll bars." + CrLf + "Close the window to see the text printed to the console." + Chr$(0)
  16.  
  17. hwRe1 = CreateWindowExA(WS_EX_CLIENTEDGE, _Offset(t0), _Offset(t1), WS_VISIBLE Or WS_CHILD or WS_VSCROLL Or WS_HSCROLL Or ES_MULTILINE Or ES_WANTRETURN, 10, 460, 400, 120, hw, 0, hi, 0): If 0 = hwRe1 Then System
  18.  

Quick test , after compiling, copy a image into the Richedit control as follows:
Navigate to qb64\source\ right click on file qb64.ico and select copy. Place mouse in Richedit control and press ctrl+v
Expected result image displayed in Rich edit control

7
Programs / Windows buttons for 32 and 64 bit IDE - Take 2
« on: October 11, 2021, 06:21:01 am »
With the release of QB64 v2.0  a seperate manifest nolonger required for Windows controls:
"Automatically embeds a manifest file when compiling an exe with $VersionInfo, so that Common Controls v6.0 gets linked at runtime."

Regarding windows controls,  I  found this page  https://www.qb64.org/forum/index.php?topic=3217.msg124966#msg124966  informative and useful. Seems it was never completed which is a shame!  However it is easy to comment and be critical of others, hence  I wrote an upgrade to give something back.

Talking about comments, you will notice  there are several lines that have comments, these are alternatives for doing the same thing. Comment an active line to disable it,  un-comment an alternative line if available to see what it does.

Save the following files and place them in your QB64 folder:

window_controls_7.bas
Code: QB64: [Select]
  1. DefStr A-Z
  2. $VersionInfo:Comments=This uses Controls! 'Creates flat controls remove for 3D
  3. Do: Loop Until _ScreenExists '             before using _WindowHandle or _title
  4. ' A Simple Window for QB64 32 & 64 bit
  5. ' window_controls_7.bas
  6. ' MPG 30-9-2021
  7. '
  8. '---------------------------------------------------------------
  9. 'NOTE:
  10. 'Create a new file WIN.h with the following content (Remove the comments '):
  11. '---Start of file contents:---
  12. 'ptrszint FUNC_WINDOWPROC(ptrszint*_FUNC_WINDOWPROC_OFFSET_HWND,uint32*_FUNC_WINDOWPROC_ULONG_UMSG,uptrszint*_FUNC_WINDOWPROC_UOFFSET_WPARAM,ptrszint*_FUNC_WINDOWPROC_OFFSET_LPARAM);
  13.  
  14. 'LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  15. ' return FUNC_WINDOWPROC((ptrszint *) (& hwnd), & uMsg, & wParam, (ptrszint *) (& lParam));
  16. '}
  17.  
  18. 'void * GetWindowProc() {
  19. ' return (void *) WindowProc;
  20. '}
  21. '---End of file contents---
  22. 'Your program uses the WIN.h file to get the WindowProc. Note: Place above file in your working folder (The QB64 folder).
  23. '----------------------------------------------------------------
  24.  
  25. '--Constants
  26.      
  27. Const IDC_ARROW = &H7F00
  28. Const COLOR_WINDOW = 5
  29.  
  30. Const WS_OVERLAPPED = 0
  31. Const WS_EX_CLIENTEDGE = &H00000200
  32. Const WS_CAPTION = &H00C00000
  33. Const WS_SYSMENU = &H00080000
  34. Const WS_THICKFRAME = &H00040000
  35. Const WS_MINIMIZEBOX = &H00020000
  36. Const WS_MAXIMIZEBOX = &H00010000
  37. Const WS_VSCROLL = &H00200000
  38. Const WS_HSCROLL = &H00100000
  39. 'Const WS_OVERLAPPEDWINDOW = WS_OVERLAPPED Or WS_CAPTION Or WS_SYSMENU Or WS_THICKFRAME Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX
  40. Const WS_OVERLAPPEDWINDOW = WS_OVERLAPPED Or WS_CAPTION Or WS_SYSMENU
  41. Const WS_TABSTOP = &H00010000
  42. Const WS_VISIBLE = &H10000000
  43. Const WS_CHILD = &H40000000
  44. Const WS_GROUP = &H00020000
  45.  
  46. Const CW_USEDEFAULT = &H80000000
  47.  
  48. Const WM_CLOSE = &H0010
  49. Const WM_CREATE = 1
  50. Const WM_DESTROY = 2
  51. Const WM_COMMAND = &H0111
  52. Const WM_SETTEXT = &H000C
  53. Const WM_GETTEXT = &H000D
  54.  
  55. Const SW_SHOWDEFAULT = &HA
  56.  
  57. Const BS_PUSHBUTTON = 0 '     Standard button
  58. Const BS_AUTOCHECKBOX = 3 '   Multi-Checkbox button
  59. Const BN_CLICKED = 0
  60. Const BS_RADIOBUTTON = 4 '     Single Radio button
  61. Const BS_AUTORADIOBUTTON = 9 ' Multi-radio buttons
  62. Const BS_GROUPBOX = 7 '        Group box "eye candy"
  63.  
  64. Const BM_GETCHECK = &HF0
  65. Const BST_CHECKED = &H1
  66. Const BM_CLICK = &H00F5
  67. Const BM_SETCHECK = &HF1
  68.  
  69. Const ES_LEFT = 0
  70. Const EM_SETPASSWORDCHAR = &HCC
  71.  
  72. Const ES_NUMBER = &H2000
  73. Const ES_PASSWORD = &H0020
  74.  
  75. Const ES_MULTILINE = 4
  76. Const ES_AUTOVSCROLL = &H0040
  77. Const ES_AUTOHSCROLL = &H0080
  78. Const ES_WANTRETURN = &H1000
  79.  
  80.  
  81. '--Types
  82.     As Long x
  83.     As Long y
  84.  
  85. Type MSG
  86.     As _Offset hwnd
  87.     As _Unsigned Long message
  88.     As _Unsigned _Offset wParam 'unsigned pointer sized integer
  89.     As _Offset lParam 'pointer sized integer
  90.     As _Unsigned Long time
  91.     As POINT pt
  92.  
  93. Type WNDCLASSA
  94.     As _Unsigned Long style
  95.     $If 64BIT Then
  96.         As String * 4 padding
  97.     $End If
  98.  
  99.     As _Offset lpfnWndProc
  100.     As Long cbClsExtra, cbWndExtra
  101.     As _Offset hInstance, hIcon, hCursor, hbrBackground, lpszMenuName, lpszClassName
  102.  
  103. '--Libaries
  104.     Function GetWindowProc%& ()
  105.  
  106.     Function SendMessageA%& (ByVal hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  107.     Function DefWindowProcA%& (ByVal hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  108.     Sub PostQuitMessage (ByVal nExitCode As Long)
  109.     Function LoadCursorW%& (ByVal hInstance As _Offset, Byval lpCursorName As _Offset)
  110.     Function RegisterClassA~% (ByVal lpWndClass As _Offset)
  111.     Function CreateWindowExA%& (ByVal dwExStyle As Long, Byval lpClassName As _Offset, Byval lpWindowName As _Offset, Byval dwStyle As Long, Byval X As Long, Byval Y As Long, Byval nWidth As Long, Byval nHeight As Long, Byval hWndParent As _Offset, Byval hMenu As _Offset, Byval hInstance As _Offset, Byval lpParam As _Offset)
  112.     Function ShowWindow& (ByVal hWnd As _Offset, Byval nCmdShow As Long)
  113.     Function UpdateWindow& (ByVal hWnd As _Offset)
  114.     Function GetMessageA% (ByVal lpMsg As _Offset, Byval hWnd As _Offset, Byval wMsgFilterMin As _Unsigned Long, Byval wMsgFilterMax As _Unsigned Long)
  115.     Function TranslateMessage& (ByVal lpMsg As _Offset)
  116.     Function DispatchMessageA%& (ByVal lpmsg As _Offset)
  117.     Sub DestroyWindow (ByVal hWnd As _Offset)
  118.     Function PostMessageA%& (ByVal hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  119.     Function SetWindowTextA& (ByVal hWnd As _Offset, Byval lpString As _Offset)
  120.     Function GetWindowLongA& (ByVal hwnd As _Offset, Byval nIndex As Long)
  121.     Function SetWindowLongA& (ByVal hwnd As _Offset, Byval nIndex As Long, Byval dwNewLong As Long)
  122.  
  123.     Function GetModuleHandleW%& (ByVal lpModuleName%&)
  124.     Function GetLastError~& ()
  125.  
  126.  
  127. '--Variables
  128.  
  129. Dim Shared hi As _Offset '   Handle to application instance
  130. Dim Shared wc As WNDCLASSA ' define wc as WNDCLASSEX structure
  131. Dim msg As MSG
  132. Dim Shared hw As _Offset '    Handle to window created
  133.  
  134. Dim Shared hwb0 As _Offset '  Handle to window button created
  135. Dim Shared hwb1 As _Offset '  Handle to window button created
  136. Dim Shared hwb2 As _Offset '  Handle to window button created
  137.  
  138. Dim Shared hwcb0 As _Offset ' Handle to window checkbox button created
  139. Dim Shared hwcb1 As _Offset ' Handle to window checkbox button created
  140. Dim Shared hwcb2 As _Offset ' Handle to window checkbox button created
  141.  
  142. Dim Shared hwgb1 As _Offset ' Handle to group box 1
  143. Dim Shared hwr11 As _Offset ' Handle to window radio botton
  144.  
  145. Dim Shared hwgb2 As _Offset ' Handle to group box 2
  146. Dim Shared hwr21 As _Offset ' Handle to window radio botton
  147.  
  148. Dim Shared hwLabel1 As _Offset
  149. Dim Shared hwLabel2 As _Offset
  150.  
  151. Dim Shared hwe1 As _Offset 'Single line edit control
  152. Dim Shared hwe2 As _Offset 'Multiline edit control
  153. Dim Shared hwLB As _Offset 'Handle to list box
  154. Dim Shared hwCB As _Offset 'Handle to combo drop-down list box
  155.  
  156. Dim Shared discardb As Long 'Dummy variable
  157. Dim Shared discardp As _Offset 'Dummy variable
  158. Dim Shared t0 As String 'Type of component
  159. Dim Shared t1 As String 'Title or componets text
  160. Dim Shared buf1 As String * 64 'Single line edit buffer
  161. Dim Shared buf2 As String * 4096 'Multi line edit buffer
  162.      
  163. Dim Shared MainClassName As String * 5
  164. MainClassName = "main" + Chr$(0)
  165.  
  166. Dim CrLf As String * 2 '    define as 2 byte STRING
  167. CrLf = Chr$(13) + Chr$(10) 'carriage return&line feed
  168.  
  169.  
  170. Dim Shared As String className '       Variable className stores name of our window class
  171. className = "myWindowClass" + Chr$(0) 'Used in wc. which in turn is used to register window class with the system.
  172.  
  173. hi = GetModuleHandleW(0) 'Handle to application instance
  174.  
  175. '---Step 1: Registering the Window Class
  176. 'Fill out the members of WNDCLASSEX structure (wc) and call RegisterClassA
  177.  
  178. wc.style = 0 '                            Class Styles (CS_*), not Window Styles (WS_*) This is usually be set to 0.
  179. wc.lpfnWndProc = GetWindowProc '          Pointer to the window procedure for this window class. (see WIN.h)
  180. wc.cbClsExtra = 0 '                       Amount of extra data allocated for this class in memory. Usually 0.
  181. wc.cbWndExtra = 0 '                       Amount of extra data allocated in memory per window of this type. Usually 0.
  182. wc.hInstance = hi '                       Handle to application instance .
  183. wc.hIcon = 0 '                            Large (usually 32x32) icon shown when the user presses Alt+Tab. Set to 0
  184. wc.hCursor = LoadCursorW(0, IDC_ARROW) '  Cursor that will be displayed over our window.
  185. wc.hbrBackground = COLOR_WINDOW 'was +1   Background Brush to set the color of our window. '
  186. wc.lpszMenuName = 0 '                     Name of a menu resource to use for the windows with this class.
  187. wc.lpszClassName = _Offset(className) '   Name to identify the class with.
  188.  
  189. If RegisterClassA(_Offset(wc)) = 0 Then
  190.     Print "RegisterClassA failed:"; GetLastError
  191.     End
  192.     'Else Print "OK"
  193.  
  194. '--Step 2: Creating the Windows
  195.  
  196. '--Main window
  197. 'After registering the class, create a window with it using CreateWindowExA.
  198.  
  199. 'HWND CreateWindowExA(
  200. '  DWORD     dwExStyle,     0                     Extended windows style. Not used set to 0
  201. '  LPCSTR    lpClassName,  _Offset(className)     Tells the system what kind of window to create.
  202. '  LPCSTR    lpWindowName, _Offset(t1)            Text displayed in the Caption or Title Bar.
  203. '  DWORD     dwStyle,      WS_OVERLAPPEDWINDOW... Window Style parameters see constants
  204. '  int       X,            CW_USEDEFAULT          Top left corner of your window. Let windows choose
  205. '  int       Y,            CW_USEDEFAULT          Top left corner of your window. Let windows choose
  206. '  int       nWidth,       432                    Width and
  207. '  int       nHeight,      400                    height of the window
  208. '  HWND      hWndParent,     0                    No parent window set handle to 0
  209. '  HMENU     hMenu,          0                    Not menu set to 0
  210. '  HINSTANCE hInstance,     hi                    Module instance handle associated with the window.
  211. ' LPVOID    lpParam         0                    Used with MDI child window not used set to 0
  212. ')
  213.  
  214. t1 = "Window Ref 1" + Chr$(0)
  215. 'hw = CreateWindowExA(0, _Offset(className), _Offset(t1), WS_HSCROLL Or WS_OVERLAPPEDWINDOW Or WS_VSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, 432, 400, 0, 0, hi, 0): If 0 = hw Then System
  216. hw = CreateWindowExA(0, _Offset(className), _Offset(t1), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 432, 520, 0, 0, hi, 0): If 0 = hw Then System
  217.  
  218. '--Standard Controls: Button, Edit, List Box etc
  219. 'Controls are just child windows. They have a procedure, a class etc... that is registered by the system.
  220. 'Anything you can do with a normal window you can do with a control.
  221.  
  222. '-Standard Buttons require style BS_PUSHBUTTON
  223.  
  224. t0 = "BUTTON" + Chr$(0) '  Set: Window control is BUTTON predefined class
  225. t1 = "Button 0" + Chr$(0) 'Set: Button display text
  226. hwb0 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_TABSTOP Or WS_VISIBLE Or WS_CHILD Or BS_PUSHBUTTON, 10, 10, 75, 23, hw, 0, hi, 0): If 0 = hwb0 Then System
  227.  
  228. t0 = "BUTTON" + Chr$(0) '  Set: Window control is BUTTON predefined class
  229. t1 = "Button 1" + Chr$(0) 'Set: Button display text
  230. hwb1 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_TABSTOP Or WS_VISIBLE Or WS_CHILD Or BS_PUSHBUTTON, 10, 37, 75, 23, hw, 0, hi, 0): If 0 = hwb1 Then System
  231.  
  232. t0 = "BUTTON" + Chr$(0) '  Set: Window control is BUTTON
  233. t1 = "Button 2" + Chr$(0) 'Set: Button display text
  234. hwb2 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_TABSTOP Or WS_VISIBLE Or WS_CHILD Or BS_PUSHBUTTON, 10, 64, 75, 23, hw, 0, hi, 0): If 0 = hwb2 Then System
  235.  
  236. '-Checkbox Buttons require style BS_AUTOCHECKBOX
  237. t0 = "BUTTON" + Chr$(0) '  Set: Window control is BUTTON
  238. t1 = "ChkBox0" + Chr$(0) 'Check box label display text
  239. hwcb0 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_TABSTOP Or WS_VISIBLE Or WS_CHILD Or BS_AUTOCHECKBOX, 10, 91, 90, 23, hw, 0, hi, 0): If 0 = hwcb0 Then System
  240.  
  241. t0 = "BUTTON" + Chr$(0) '  Set: Window control is BUTTON
  242. t1 = "ChkBox1" + Chr$(0) 'Check box label display text
  243. hwcb1 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_TABSTOP Or WS_VISIBLE Or WS_CHILD Or BS_AUTOCHECKBOX, 10, 118, 90, 23, hw, 0, hi, 0): If 0 = hwcb1 Then System
  244.  
  245. t0 = "BUTTON" + Chr$(0) '  Set: Window control is BUTTON
  246. t1 = "ChkBox2" + Chr$(0) 'Check box label display text
  247. hwcb2 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_TABSTOP Or WS_VISIBLE Or WS_CHILD Or BS_AUTOCHECKBOX, 10, 145, 90, 23, hw, 0, hi, 0): If 0 = hwcb2 Then System
  248.  
  249.  
  250. 'Standard Radio Buttons require style BS_RADIOBUTTON (single) or BS_AUTORADIOBUTTON (group)
  251. 'First button of a group must have following styles WS_TABSTOP WS_GROUP
  252. 'The first control after last group must have style WS_GROUP to terminate last group
  253. 'Note: A BS_GROUPBOX is "eye candy" and does not contribute to a radio box group.
  254. ' The crucial parameter to control radio or check box grouping is the style WS_GROUP
  255.  
  256. '--Bank 1: Group box1
  257. t0 = "BUTTON" + Chr$(0) 'predefined class
  258. t1 = "Group box1" + Chr$(0)
  259. hwgb1 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_VISIBLE Or WS_CHILD Or BS_GROUPBOX, 100, 10, 300, 50, hw, 0, hi, 0): If 0 = hwgb1 Then System
  260. t1 = "Radio 11" + Chr$(0)
  261. hwr11 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_VISIBLE Or WS_CHILD Or BS_AUTORADIOBUTTON Or WS_TABSTOP Or WS_GROUP, 105, 30, 90, 23, hw, 0, hi, 0): If 0 = hwr11 Then System
  262. t1 = "Radio 12" + Chr$(0)
  263. hwr12 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_VISIBLE Or WS_CHILD Or BS_AUTORADIOBUTTON, 200, 30, 90, 23, hw, 0, hi, 0): If 0 = hwr12 Then System
  264. t1 = "Radio 12" + Chr$(0)
  265. hwr13 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_VISIBLE Or WS_CHILD Or BS_AUTORADIOBUTTON, 300, 30, 90, 23, hw, 0, hi, 0): If 0 = hwr13 Then System
  266.  
  267. '--Bank 2: Group box2
  268. t0 = "BUTTON" + Chr$(0) 'predefined class
  269. t1 = "Group box2" + Chr$(0)
  270. hwgb2 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_VISIBLE Or WS_CHILD Or BS_GROUPBOX, 100, 70, 300, 50, hw, 0, hi, 0): If 0 = hwgb2 Then System
  271. t1 = "Radio 21" + Chr$(0)
  272. hwr21 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_VISIBLE Or WS_CHILD Or BS_AUTORADIOBUTTON Or WS_TABSTOP Or WS_GROUP, 105, 90, 90, 23, hw, 0, hi, 0): If 0 = hwr21 Then System
  273. t1 = "Radio 22" + Chr$(0)
  274. hwr22 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_VISIBLE Or WS_CHILD Or BS_AUTORADIOBUTTON, 200, 90, 90, 23, hw, 0, hi, 0): If 0 = hwr22 Then System
  275. t1 = "Radio 23" + Chr$(0)
  276. hwr23 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_VISIBLE Or WS_CHILD Or BS_AUTORADIOBUTTON, 300, 90, 90, 23, hw, 0, hi, 0): If 0 = hwr23 Then System
  277.  
  278. '--Label1
  279. t0 = "STATIC" + Chr$(0) 'predefined class
  280. t1 = "Label1 Enter your score:" + Chr$(0)
  281. hwLabel1 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_VISIBLE Or WS_CHILD, 100, 125, 372, 16, hw, 0, hi, 0): If 0 = hwLabel1 Then System
  282.  
  283. '--Label2
  284. t0 = "STATIC" + Chr$(0) 'predefined class
  285. t1 = "Label2 Enter your name:" + Chr$(0)
  286. hwLabel2 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_VISIBLE Or WS_CHILD, 100, 142, 372, 16, hw, 0, hi, 0): If 0 = hwLabel2 Then System
  287.  
  288. '--Edit single line
  289.  
  290. t0 = "EDIT" + Chr$(0) 'predefined class
  291. t1 = "This is a edit control." + Chr$(0)
  292. hwe1 = CreateWindowExA(WS_EX_CLIENTEDGE, _Offset(t0), _Offset(t1), WS_TABSTOP Or WS_VISIBLE Or WS_CHILD Or ES_LEFT, 12, 175, 372, 26, hw, 0, hi, 0): If 0 = hwe1 Then System
  293.  
  294. '---Edit  multiline control
  295.  
  296. t0 = "EDIT" + Chr$(0) 'predefined class
  297. t1 = "This is a" + CrLf + "multiline edit control." + CrLf + "Click in me and type." + CrLf + "It should scroll automatically in both directions, but there aren't any scroll bars." + CrLf + "Close the window to see the text printed to the console." + Chr$(0)
  298. hwe2 = CreateWindowExA(WS_EX_CLIENTEDGE, _Offset(t0), _Offset(t1), WS_VSCROLL Or WS_HSCROLL Or WS_TABSTOP Or WS_VISIBLE Or WS_CHILD Or ES_AUTOHSCROLL Or ES_AUTOVSCROLL Or ES_LEFT Or ES_MULTILINE Or ES_WANTRETURN, 10, 210, 400, 120, hw, 0, hi, 0): If 0 = hwe2 Then System
  299.  
  300. '---List box control
  301. Const LBS_NOTIFY = 1
  302. t0 = "LISTBOX" + Chr$(0) 'predefined class
  303. hwLB = CreateWindowExA(WS_EX_CLIENTEDGE, _Offset(t0), 0, WS_CHILD Or WS_VISIBLE Or LBS_NOTIFY Or WS_VSCROLL Or ES_AUTOVSCROLL, 10, 340, 150, 120, hw, 0, hi, 0): If 0 = hwLB Then System
  304.  
  305. '---Combo drop-down List control
  306. Const CBS_READONLY = &H1000 'Remove to edit selection
  307. Const CBS_NOTIFY = &H0008
  308. Const CBS_DROPDOWN = 2
  309. Const CBS_DROPDOWNLIST = 3
  310. t0 = "COMBOBOX" + Chr$(0) 'predefined class
  311. hwCB = CreateWindowExA(WS_EX_CLIENTEDGE, _Offset(t0), 0, WS_CHILD Or WS_VISIBLE Or CBS_DROPDOWNLIST Or CBS_READONLY, 170, 340, 150, 110, hw, 0, hi, 0): If 0 = hwCB Then System
  312.  
  313. '--hwCB Add items to combo box
  314. Const CB_ADDSTRING = 323
  315. For j = 1 To 10
  316.     t0 = "Combo box Item" + Str$(j) + Chr$(0)
  317.     discardp = SendMessageA(hwCB, CB_ADDSTRING, 0, _Offset(t0)) ' Add text
  318. '--End hwCB Add items to combo box
  319.  
  320. '--hwCB Initialize combo control default selection. Note -1 no selection
  321. Dim Shared CB_selected_item As Long 'Ref selection
  322. CB_selected_item = 7 'set initial selection value
  323.  
  324. 'Zero index. Note index 2 selects the third element
  325. Const CB_SETCURSEL = 334 'Set selection
  326. discardp = SendMessageA(hwCB, CB_SETCURSEL, CB_selected_item, 0)
  327. 'discardp = SendMessageA(hwCB, CB_SETCURSEL, -1, 0) 'No selection
  328. '---End combo control
  329.  
  330.  
  331. '--hwLB Add items to list box
  332. Const LB_ADDSTRING = &H180
  333. For i = 1 To 10
  334.     t0 = "List Box Item" + Str$(i) + Chr$(0)
  335.     discardp = SendMessageA(hwLB, LB_ADDSTRING, 0, _Offset(t0)) ' Add text
  336. '--End hwLB Add items to list box
  337.  
  338. '--hwLB Initialize list control default selection. Note -1 no selection
  339. 'Zero index. Note index 2 selects the third element
  340. Const LB_SETCURSEL = &H186 'Set selection
  341. Dim Shared LB_selected_item As Long 'Ref selection
  342. LB_selected_item = 8 'set initial selection value
  343. discardp = SendMessageA(hwLB, LB_SETCURSEL, LB_selected_item, 0)
  344. 'discardp = SendMessageA(hwLB, LB_SETCURSEL, -1, 0) 'No selection
  345. '---End list control
  346.  
  347. '--Initialize set initial conditions
  348. discardp = SendMessageA(hwcb1, BM_SETCHECK, BST_CHECKED, 0) 'Set check box
  349. discardp = SendMessageA(hwr13, BM_SETCHECK, BST_CHECKED, 0) 'Set radio button
  350. discardp = SendMessageA(hwr23, BM_SETCHECK, BST_CHECKED, 0) 'Set radio button
  351.  
  352. t0 = "CLOSE" + Chr$(0) '  Text to send to buttton Button2
  353. 'discardp = SetWindowTextA&(hwb2, _Offset(t0)) '             Method 1 Change button text from Button2 to Close
  354. discardp = SendMessageA(hwb2, WM_SETTEXT, 0, _Offset(t0)) '  Method 2 Alternative
  355.  
  356. t0 = "Label2 text changed ?" + Chr$(0) '    Text to send to Label2
  357. 'discardp = SetWindowTextA&(hwLabel2, _Offset(t0)) '             Method 1
  358. discardp = SendMessageA(hwLabel2, WM_SETTEXT, 0, _Offset(t0)) ' Method 2 Alternative
  359.  
  360. t0 = "Edit control:" + Chr$(0) '             Text to send to Edit control
  361. 'discardp = SetWindowTextA&(hwe1, _Offset(t0)) '            Method 1
  362. discardp = SendMessageA(hwe1, WM_SETTEXT, 0, _Offset(t0)) ' Method 2 Alternative
  363.  
  364. 'discardp = SendMessageA(hwe1, EM_SETPASSWORDCHAR, 0, 0) '        Edit control Remove password character
  365. 'discardp = SendMessageA(hwe1, EM_SETPASSWORDCHAR, Asc("*"), 0) ' Edit control Set password character
  366.  
  367. 'Dim Shared winstyle As Long 'current window style variable
  368. Const GWL_STYLE = -16 'Window style command
  369.  
  370. 'winstyle = GetWindowLongA(hwe1, GWL_STYLE)
  371. 'discardp = SetWindowLongA(hwe1, GWL_STYLE, winstyle Or ES_NUMBER) '     Add number style
  372.  
  373. 'winstyle = GetWindowLongA(hwe1, GWL_STYLE)
  374. 'discardp = SetWindowLongA(hwe1, GWL_STYLE, winstyle And Not ES_NUMBER) 'Remove number style
  375.  
  376. '--End Initialize set initial conditions
  377.  
  378. '----How to set top/bottom margins of a Win32 Edit control "hwe2"
  379.     Function GetWindowRect& (ByVal hWnd As _Offset, Byval lpRect As _Offset)
  380.     Function GetClientRect& (ByVal hWnd As _Offset, Byval lpRect As _Offset)
  381.     Function InflateRect& (ByVal lpRect As _Offset, Byval x As Long, Byval y As Long)
  382. Type RECT
  383.     As Long left, top, right, bottom
  384. Dim As RECT rect
  385. Const EM_SETRECT = &H00B3
  386. If GetClientRect(hwe2, _Offset(rect)) Then
  387.     Print rect.left, rect.top, rect.right, rect.bottom
  388.  
  389.     If InflateRect(_Offset(rect), -5, -5) Then
  390.         Print rect.left, rect.top, rect.right, rect.bottom
  391.         ' Edit control set margin
  392.         If SendMessageA(hwe2, EM_SETRECT, 0, _Offset(rect)) Then ' Edit control set margin
  393.             Print "margin set hwe2"
  394.         End If
  395.     End If
  396.  
  397.  
  398. 'Display and Update window to ensure it has properly redrawn itself on the screen.
  399. discardb = ShowWindow(hw, SW_SHOWDEFAULT)
  400. discardb = UpdateWindow(hw)
  401.  
  402. '-- Step 3: The Message Loop
  403. While GetMessageA(_Offset(msg), 0, 0, 0) > 0 '   gets a message from your application's message queue.
  404.     discardb = TranslateMessage(_Offset(msg)) '  performs some additional processing on keyboard events
  405.     discardp = DispatchMessageA(_Offset(msg)) '  sends the message out to the window that the message was sent to
  406.  
  407.  
  408. Print "End"
  409. '####== End program ==###
  410.  
  411. '-- Step 4: the Window Procedure
  412. Function WindowProc%& (hWnd As _Offset, uMsg As _Unsigned Long, wParam As _Unsigned _Offset, lParam As _Offset)
  413.     Dim As String a, srch, replace
  414.  
  415.     Select Case uMsg
  416.  
  417.         ' Case WM_CREATE
  418.         '     WindowProc = 0
  419.  
  420.         Case WM_CLOSE
  421.             discardp = SendMessageA(hwe2, WM_GETTEXT, Len(buf2), _Offset(buf2)) 'Get text
  422.             Print: Print "First part of the edit control text:": Print
  423.  
  424.             a$ = _Trim$(buf2) '                      Remove spaces
  425.             a$ = Left$(a$, InStr(a$, Chr$(0)) - 1) ' Buffer contains a null terminated string. Find position of null.
  426.             buf2 = "" '                              Extract characters upto this null character. Clear buffer
  427.  
  428.             '----Remove unwanted CRLF---
  429.             srch$ = Chr$(13) + Chr$(10)
  430.             replace$ = Chr$(10)
  431.             Do While InStr(a$, srch$)
  432.                 a$ = Mid$(a$, 1, InStr(a$, srch$) - 1) + replace$ + Mid$(a$, InStr(a$, srch$) + Len(srch$))
  433.             Loop
  434.             '-----END remove-------------
  435.  
  436.  
  437.             Print a$
  438.  
  439.             Print "Radio 11: 0x"; Hex$(SendMessageA(hwr11, BM_GETCHECK, 0, 0))
  440.             Print "Radio 12: 0x"; Hex$(SendMessageA(hwr12, BM_GETCHECK, 0, 0))
  441.             If SendMessageA(hwcb1, BM_GETCHECK, 0, 0) = BST_CHECKED Then
  442.                 Print: Print "Check box is checked:": Print
  443.             End If
  444.  
  445.  
  446.             DestroyWindow (hWnd) 'Destroy window and child windows
  447.             WindowProc = 0
  448.  
  449.         Case WM_DESTROY
  450.             PostQuitMessage 0 'Want to exit the program
  451.             WindowProc = 0
  452.  
  453.         Case WM_COMMAND
  454.             '===============
  455.  
  456.             '---Respond to Listbox selection
  457.             Const LBN_SELCHANGE = 1
  458.             Const LB_GETCURSEL = &H188 ' get index of currently selected item in listbox
  459.             Const LB_GETTEXT = &H189 '   get selected item text
  460.  
  461.             Dim LBwParm As Long
  462.             Dim selectedIndexLB As _Offset 'item selected returned as offset
  463.             Dim tempLB As Long '            temp variable
  464.             Dim textBuffLB As String * 32 ' Buffer to store selected string
  465.  
  466.             LBwParm = ConvertOffset&&(wParam) ' Convert to long
  467.  
  468.             'listbox hwLB selection changed
  469.             If (HIWORD(LBwParm) = LBN_SELCHANGE) And (lParam = hwLB) Then
  470.                 selectedIndexLB = SendMessageA(hwLB, LB_GETCURSEL, 0, 0) 'Get current selection
  471.                 tempLB = ConvertOffset&&(selectedIndexLB) '               convert to long
  472.                 '--Get item text store in buffer
  473.                 discardp = SendMessageA(hwLB, LB_GETTEXT, tempLB, _Offset(textBuffLB))
  474.  
  475.                 Print "LBzzzzzzz", LBwParm, HIWORD(LBwParm)
  476.                 Print "List box selection = "; tempLB
  477.                 Print textBuffLB
  478.                 WindowProc = 0
  479.             End If
  480.             '---End Respond to Listbox selection
  481.  
  482.  
  483.             '---Respond to Combo Listbox selection
  484.             Const CBN_SELCHANGE = 1
  485.             Const CB_GETCURSEL = 327 ' get index of currently selected item in combo listbox
  486.             Const CB_GETLBTEXT = 328 ' get selected item text
  487.  
  488.             Dim CBwParm As Long
  489.             Dim selectedIndexCB As _Offset 'item selected returned as offset
  490.             Dim tempCB As Long '            temp variable
  491.             Dim textBuffCB As String * 32 ' Buffer to store selected string
  492.  
  493.             CBwParm = ConvertOffset&&(wParam) 'Convert to long
  494.  
  495.             'Combo listbox hwCB selection changed
  496.             If (HIWORD(CBwParm) = CBN_SELCHANGE) And (lParam = hwCB) Then
  497.                 selectedIndexCB = SendMessageA(hwCB, CB_GETCURSEL, 0, 0) 'Get current selection
  498.                 tempCB = ConvertOffset&&(selectedIndexCB) '               convert to long
  499.                 '--Get item text store in buffer
  500.                 discardp = SendMessageA(hwCB, CB_GETLBTEXT, tempCB, _Offset(textBuffCB))
  501.  
  502.                 Print "CBxxxxxx", LBwParm, HIWORD(LBwParm)
  503.                 Print "Combo box selection = "; tempCB
  504.                 Print textBuffCB
  505.                 WindowProc = 0
  506.             End If
  507.             '---End Respond to Combo Listbox selection
  508.  
  509.  
  510.             '=====================
  511.             If wParam = BN_CLICKED Then
  512.                 Select Case lParam
  513.                     'A button was clicked test each one
  514.  
  515.                     '---Three standard buttons---
  516.                     Case hwb0
  517.                         Print "Button 0 pressed"
  518.                         WindowProc = 0
  519.                     Case hwb1
  520.                         'Get input text and copy to buffer (1)
  521.  
  522.                         discardp = SendMessageA(hwe1, WM_GETTEXT, Len(buf1), _Offset(buf1)) 'Read text from Edit control into buf1
  523.                         Print "Button 1 pressed"
  524.                         a$ = Left$(buf1, InStr(buf1, Chr$(0)) - 1) 'Buffer contains a null terminated string. Find position of null.
  525.                         Print "Button 1 pressed. Text read from edit control: ### " + a$ + " ###" '                  Extract characters upto this null character.
  526.                         buf1 = "" '                                 Clear buffer
  527.  
  528.                         WindowProc = 0
  529.                     Case hwb2
  530.                         Print "Button 2 pressed Also used as close button"
  531.                         discardp = PostMessageA(hWnd, WM_CLOSE, 0, 0) 'Use a button close Close
  532.                         WindowProc = 0
  533.                         '---End standard buttons---
  534.  
  535.                         '---Three checkbox standard buttons---
  536.                     Case hwcb0
  537.                         Print "Check box 0 click"
  538.                         If SendMessageA(hwcb0, BM_GETCHECK, 0, 0) = BST_CHECKED Then
  539.                             Print "Check box 0 is checked:"
  540.                         Else
  541.                             Print "Check box 0 is un-checked:"
  542.                         End If
  543.                         WindowProc = 0
  544.                     Case hwcb1
  545.                         Print "Check box 1 click"
  546.                         WindowProc = 0
  547.                     Case hwcb2
  548.                         Print "Check box 2 click"
  549.                         WindowProc = 0
  550.                         '---End checkbox standard buttons---
  551.  
  552.                         '---Bank 1 - Radio buttons---
  553.                     Case hwr11
  554.                         Print "Radio 11 clicked"
  555.                         WindowProc = 0
  556.                     Case hwr12
  557.                         Print "Radio 12 clicked"
  558.                         WindowProc = 0
  559.                     Case hwr13
  560.                         Print "Radio 13 clicked"
  561.                         WindowProc = 0
  562.                         '---End Bank 1 - Radio buttons---
  563.  
  564.                         '---Bank 2 - Radio buttons---
  565.                     Case hwr21
  566.                         Print "Radio 21 clicked"
  567.                         If SendMessageA(hwr21, BM_GETCHECK, 0, 0) = BST_CHECKED Then
  568.                             Print: Print "Button Radio 21 is checked:": Print
  569.                         End If
  570.                         WindowProc = 0
  571.                     Case hwr22
  572.                         Print "Radio 22 clicked"
  573.                         WindowProc = 0
  574.                     Case hwr23
  575.                         Print "Radio 23 clicked"
  576.  
  577.                         '---End Bank 2 - Radio buttons---
  578.  
  579.                 End Select
  580.             Else
  581.                 'Not our message send back to system for processing
  582.                 WindowProc = DefWindowProcA(hWnd, uMsg, wParam, lParam)
  583.             End If
  584.  
  585.             WindowProc = DefWindowProcA(hWnd, uMsg, wParam, lParam)
  586.         Case Else
  587.             'Not our message send back to system for processing
  588.             WindowProc = DefWindowProcA(hWnd, uMsg, wParam, lParam)
  589.     End Select
  590.  
  591. Function ConvertOffset&& (value As _Offset)
  592.     Dim m As _MEM 'Define a memblock
  593.     m = _Mem(value) 'Point it to use value
  594.     $If 64BIT Then
  595.         Dim temp As _Integer64
  596.         'On 64 bit OSes, an OFFSET is 8 bytes in size.  We can put it directly into an Integer64
  597.         _MemGet m, m.OFFSET, temp
  598.         ConvertOffset = temp
  599.     $Else
  600.         Dim temp As Long
  601.         'However, on 32 bit OSes, an OFFSET is only 4 bytes.  We need to put it into a LONG variable first
  602.         _MemGet m, m.OFFSET, temp 'Like this
  603.         ConvertOffset = temp 'And then assign that long value to ConvertOffset&&
  604.     $End If
  605.     _MemFree m 'Free the memblock
  606.  
  607. Function HIWORD% (dw As Long)
  608.     If dw And &H80000000 Then
  609.         HIWORD = (dw \ 65535) - 1
  610.     Else
  611.         HIWORD = dw \ 65535
  612.     End If
  613.  
  614. Function LOWORD% (dw As Long)
  615.     If dw And &H8000& Then
  616.         LOWORD = &H8000 Or (dw And &H7FFF&)
  617.     Else
  618.         LOWORD = dw And &HFFFF&
  619.     End If
  620.  
WIN.h
Code: QB64: [Select]
  1. ptrszint FUNC_WINDOWPROC(ptrszint*_FUNC_WINDOWPROC_OFFSET_HWND,uint32*_FUNC_WINDOWPROC_ULONG_UMSG,uptrszint*_FUNC_WINDOWPROC_UOFFSET_WPARAM,ptrszint*_FUNC_WINDOWPROC_OFFSET_LPARAM);
  2.  
  3. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  4.  return FUNC_WINDOWPROC((ptrszint *) (& hwnd), & uMsg, & wParam, (ptrszint *) (& lParam));
  5. }
  6.  
  7. void * GetWindowProc() {
  8.  return (void *) WindowProc;
  9. }
  10.  
Result shown below:
 
window_controls_7.png


Note: For an example of subclassing a control see the edit control on the following page: https://www.qb64.org/forum/index.php?topic=4111.msg136749#msg136749




8
QB64 Discussion / Re: InputBox
« on: October 11, 2021, 04:49:46 am »
With the release of QB64 v2.0  I have updated the input box code.   
I finally managed to get subclassing to compile on both 32 and 64 bit versions of QB64. Solution in part was to update appropriate functions. However real solution came with the beta releases of QB64 v2.0 allowing the 64bit input box version to compile. 

The following provides a quick overview of subclassing:
"Subclassing is a technique that allows an application to intercept and process messages sent or posted to a particular window before the window has a chance to process them. By subclassing a window, an application can augment, modify, or monitor the behavior of the window."

"An application subclasses a window by replacing the address of the window's original window procedure with the address of a new window procedure, called the subclass procedure. Thereafter, the subclass procedure receives any messages sent or posted to the window."

Save the following files and place them in your QB64 folder:

input_box_example.bas
Code: QB64: [Select]
  1. $VersionInfo:Comments=This uses Subclassing Controls!
  2.  
  3. '$Include:'input_box.BI'
  4.  
  5. '===Your program START ==========
  6. Screen _NewImage(400, 300, 32) '             Set main screen size
  7. Color _RGB(0, 0, 0), _RGB32(205, 238, 205) ' Set colors
  8. _Title "Main Program" ' Set your main program title
  9.  
  10. 'Examples:
  11.  
  12. 'Accepts alpha-numeric characters
  13. Print "=1a= " + InputBoxM("", "", "", "", "")
  14. Print "=1b= " + InputBox
  15.  
  16.  
  17. 'Allows alpha-numeric and extra valid characters.
  18. Print "=2a= " + InputBoxM("Any character:", "All A+", "", "A+", "")
  19. Print "=2b= " + InputBoxA("Any character:", "All A+")
  20.  
  21. 'Only numeric characters allowed
  22. Print "=3a= " + InputBoxM("Digits 0-9 only", "NUMERIC", "", "N", "")
  23. Print "=3b= " + InputBoxN("Digits 0-9 only", "NUMERIC")
  24.  
  25. 'Password entry. Display asterisk
  26. Print "=4a= " + InputBoxM("Asterisk mask:", "PASSWORD 1", "", "", "A")
  27. Print "=4b= " + InputBoxP("Asterisk mask:", "PASSWORD 1")
  28.  
  29. 'Password entry. Display bullet
  30. Print "=5a= " + InputBoxM("Bullet mask:", "PASSWORD 2", "", "", "B")
  31. Print "=5b= " + InputBoxPB("Bullet mask:", "PASSWORD 2")
  32.  
  33.  
  34. Print "=7= " + InputBoxM("Limit 4 characters:", "LIMIT", "4", "", "") '
  35. Print "=8= " + InputBoxM("Digits 0-9 and associated characters", "NUMERIC+", "", "N+", "")
  36.  
  37. Print "End"
  38. '===Your program END ============
  39.  
  40. '$Include:'input_box.BM'
  41.  

input_box.BI
Code: QB64: [Select]
  1. '###_start_BI_inputbox
  2. Do: Loop Until _ScreenExists 'run before using _WindowHandle or _title
  3. $If 64BIT Then
  4.     $If VERSION < 1.6 Then
  5.         $ERROR Requires Windows QB64 version 1.6 or above
  6.     $End If
  7.  
  8. $If 32BIT Then
  9.     $If VERSION < 1.5 Then
  10.         $ERROR Requires Windows QB64 version 1.5 or above
  11.     $End If
  12.  
  13. '===================================================================
  14. 'Input box for QB64 32 & 64 bit.
  15. 'The QB64 InputBoxM function displays a pop-up dialog box,
  16. 'prompting the user for input. It has OK and Cancel buttons.
  17. 'Function returns a text string containing the user's input
  18. 'when OK button clicked. Returns an empty text string when
  19. 'Cancel button is clicked.
  20. '
  21. ' mpg_input_box_1.bas
  22. ' MPG 9-10-2021
  23. '====================================================================
  24. 'InputBoxM function:
  25. 'InputBoxM (prompt$,title$,length$,numeric$,pwMask$)
  26. '
  27. 'prompt$  - text displayed above the edit control to prompt user e.g. "Please enter a number:".
  28. 'title$   - text displayed in the title bar of the InputBoxM.
  29. 'length$  - maximum number of characters a user allowed to enter.
  30. 'numeri$c - select numeric input. Options are:
  31. '            ""   Default, allows alpha-numeric characters.
  32. '            "A+" Allows alpha-numeric and extra valid characters.
  33. '            "N"   Numeric digits 0-9 only
  34. '            "N+"  Numeric digits 0-9 and associated characters.
  35. 'pwMask$  - select a password mask' Options are:
  36. '            ""  Default no mask
  37. '            "A" Password mask Asterisk
  38. '            "B" Password mask Bullet
  39. '
  40. ' Note1: All variables are optional. Unused variables use a null string.
  41. ' Note2: Pressing cancel button returns a null string e.g ""
  42. ' Note3: You can change default values e.g valid characters, length etc
  43. '        Defaults, located in "Sub inputbox_init" or "Function InputBoxM"
  44. '----------------------------------------------------------------------
  45. 'Predefined functions:
  46. 'Based on the above, five predefined InputBox functions are
  47. 'included as follows:
  48. '
  49. 'InputBox                    - Accepts alpha-numeric characters
  50. 'InputBoxA(prompt$, title$)  - Accepts any character input
  51. 'InputBoxN(prompt$, title$)  - Only numeric characters allowed
  52. 'InputBoxP(prompt$, title$)  - Password entry. Display asterisk
  53. 'InputBoxPB(prompt$, title$) - Password entry. Display bullet
  54. '
  55. ' Note1: Variables are optional. Unused variables use a null string
  56. '----------------------------------------------------------------------
  57. ' VB Inputbox has some limitations as does the edit control. This QB64
  58. ' input box addresses these limitation.
  59. ' 1) Default character length 0x7FFE to 0x7FFFFFFE os dependent.
  60. '    Added option to limit number of characters.
  61. ' 2) Default password mask was an asterisk. Added option to select
  62. '    asterisk or bullet.
  63. ' 3) Numeric characters limited to digits 0-9 added option to have
  64. '    extra associated characters e.g calculator +-%= etc.
  65. '
  66. ' Using subclassing added the following:
  67. ' 4) Disabled context menu (Mouse Right click) copy and paste .
  68. ' 5) Disabled copy and paste using  Ctrl+c Ctrl+v.
  69. ' 6) Disabled copy and paste using Ctrl+Shift+c Ctrl+Shift+v.
  70. ' 7) Disabled annoying beep when pressing enter key.
  71. ' 8) Character validation.
  72. ' 9) Invalid character user alert. Uses MessageBeep.
  73. '
  74. '----------------------------------------------------------------------
  75. ' Code based on ideas from the following references:
  76. ' 1) Windows buttons for 32 and 64 bit IDE
  77. '    https://www.qb64.org/forum/index.php?topic=3217.msg124966#msg124966
  78. ' 2) Base64 Encoding/Decoding with Windows, Mac, and Linux
  79. '    https://www.qb64.org/forum/index.php?topic=3214.msg124919#msg124919
  80. ' 3) Threading
  81. '    https://www.qb64.org/forum/index.php?topic=3865.msg132124#msg132124
  82. '=======================================================================
  83. '
  84. '-----------------------------------------------------------------------
  85. 'NOTE:
  86. 'Create a new file input_box_WIN.h with the following content (Remove the comments '):
  87. '---Start of file contents:---
  88.      
  89. 'ptrszint FUNC_WINDOWPROC(ptrszint*_FUNC_WINDOWPROC_OFFSET_HWND,uint32*_FUNC_WINDOWPROC_ULONG_UMSG,uptrszint*_FUNC_WINDOWPROC_UOFFSET_WPARAM,ptrszint*_FUNC_WINDOWPROC_OFFSET_LPARAM);
  90. 'LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  91. ' return FUNC_WINDOWPROC((ptrszint *) (& hwnd), & uMsg, & wParam, (ptrszint *) (& lParam));
  92. '}
  93. 'void * GetWindowProc() {
  94. ' return (void *) WindowProc;
  95. '}
  96.      
  97. 'ptrszint FUNC_SUBEDIT(ptrszint*_FUNC_SUBEDIT_OFFSET_HWND,uint32*_FUNC_SUBEDIT_ULONG_UMSG,uptrszint*_FUNC_SUBEDIT_UOFFSET_WPARAM,ptrszint*_FUNC_SUBEDIT_OFFSET_LPARAM);
  98. 'LRESULT CALLBACK SubEdit(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  99. ' return FUNC_SUBEDIT((ptrszint *) (& hwnd), & uMsg, & wParam, (ptrszint *) (& lParam));
  100. '}
  101. 'void * GetSubEdit() {
  102. ' return (void *) SubEdit;
  103. '}
  104.      
  105. '---End of file contents---
  106. 'Input box uses the input_box_WIN.h file to get the WindowProc and SubEdit . Note: Place above file in your working folder (The QB64 folder).
  107. '----------------------------------------------------------------
  108.      
  109. '==Note: InputBox requires this section to be added to your program.==========
  110. 'Creates a global variable ipb. Its corresponding elements, are also global.
  111. Dim Shared ipb As input_box_udt 'The input_box_udt user defined type
  112. inputbox_init '                  Define ipb structure and initialize elements
  113.      
  114. '*****Subclassing
  115. Dim Shared OldWindowProc As Long 'Global variable store old windows process
  116. '*****End Subclassing
  117.  
  118. '###_end_BI_inputbox
  119.  

input_box.BM
Code: QB64: [Select]
  1. '###_start_BM_inputbox
  2. '######--INPUT BOX FUNCTIONS and SUBS--######################################
  3.  
  4. '--inputbox_init:  Creates a user defined type. This type is used to create
  5. '                  global variable ipb. Its corresponding elements are
  6. '                  global. Some variables are initialised in this function.
  7.  
  8. Sub inputbox_init
  9.     Const FALSE = 0
  10.     Const TRUE = Not FALSE
  11.  
  12.     Type input_box_udt
  13.         buf As String * 64 '  Buffer to store entered characters
  14.         hw As _Offset '       Pointer to inputbox window
  15.         hwLabel As _Offset '  Pointer to label
  16.         hwb0 As _Offset '     Pointer button 0 - OK
  17.         hwb1 As _Offset '     Pointer button 1 - Cancel
  18.         hwe As _Offset '      Pointer to single line edit control
  19.  
  20.         pw_mask As Integer '   Enable password mask flag
  21.         pw_bullet As Integer ' Password mask bullet flag
  22.         max_length As Integer 'Maximum allowed characters
  23.  
  24.         caption_text As String 'Window title
  25.         prompt_text As String ' Instructions to user
  26.         valid_str As String '   All allowed characters
  27.  
  28.         button0_text As String ' Left button
  29.         button1_text As String ' Right button
  30.  
  31.         x As Long 'Position of inputbox
  32.         y As Long 'Position of inputbox
  33.         max_char_allowed As Long ' Maximum number of input characters allowed
  34.     End Type
  35.  
  36.     '---Set default values
  37.     ipb.button0_text = "OK"
  38.     ipb.button1_text = "Cancel"
  39.  
  40.     '---Center InputBox window
  41.     Dim As Long userwidth, userheight
  42.     userwidth = _DesktopWidth: userheight = _DesktopHeight 'get current screen resolution
  43.  
  44.     ipb.x = (userwidth \ 2 - 358 \ 2) - 3
  45.     ipb.y = (userheight \ 2 - 136 \ 2) - 29
  46. '-- END inputbox_init:
  47.  
  48. 'Predefined function 1: - Allow numeric and alpha characters
  49. Function InputBox$ ()
  50.     InputBox = InputBoxM("", "", "", "", "")
  51.  
  52. 'Predefined function 2: - Allows alpha-numeric and extra valid characters.
  53. Function InputBoxA$ (prompt As String, title As String)
  54.     InputBoxA = InputBoxM(prompt, title, "", "A+", "")
  55.  
  56. 'Predefined function 3: - Only numeric characters allowed.
  57. Function InputBoxN$ (prompt As String, title As String)
  58.     InputBoxN = InputBoxM(prompt, title, "", "N", "")
  59.  
  60. 'Predefined function 4: - Password entry. Display asterisk.
  61. Function InputBoxP$ (prompt As String, title As String)
  62.     InputBoxP = InputBoxM(prompt, title, "", "", "A")
  63.  
  64. 'Predefined function 5: - Password entry. Display bullet.
  65. Function InputBoxPB$ (prompt As String, title As String)
  66.     InputBoxPB = InputBoxM(prompt, title, "", "", "B")
  67.  
  68.  
  69.  
  70. '---Main input box
  71. Function InputBoxM$ (prompt As String, title As String, maxLength As String, numeric As String, pwMask As String)
  72.     Const FALSE = 0
  73.     Const TRUE = Not FALSE
  74.     Dim As String str1, str2, str3, str4
  75.  
  76.     '---Set prompt text
  77.     ipb.prompt_text = "Enter some text:" 'Default value
  78.     If prompt <> "" Then
  79.         ipb.prompt_text = prompt 'Label text. User instrutions
  80.     End If
  81.  
  82.     '---Set pop-up window title (caption) text
  83.     ipb.caption_text = "InputBox" 'Default value
  84.     If title <> "" Then
  85.         ipb.caption_text = title 'User pop-up window title
  86.     End If
  87.  
  88.     '--Set maximum number of characters allowed
  89.     ipb.max_length = 40 'Default allowed characters 40
  90.     If maxLength <> "" Then
  91.         ipb.max_length = Val(maxLength) 'Required length
  92.     End If
  93.  
  94.     '---Set allowed characters.
  95.     'numeric: Options are
  96.     '  ""    Default, allows alpha-numeric characters.
  97.     '  "A+"  Allows alpha-numeric and extra valid characters.
  98.     '  "N"   Numeric digits 0-9 only
  99.     '  "N+"  Numeric digits 0-9 and associated characters.
  100.  
  101.     str1 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 'Alpha
  102.     str2 = "0123456789 " ' numeric
  103.     str3 = Chr$(34) + "!$%^&()+{}[]:@#<>?" ' Extra associated alpha/numeric characters
  104.     str4 = "%^.+-*/=" '      Associated numeric characters e.g basic calculator
  105.  
  106.     ipb.valid_str = ""
  107.  
  108.     If numeric = "" Then '                  Set default alpha numeric characters
  109.         ipb.valid_str = str1 + str2 '       Valid alpha/numeric characters
  110.     End If
  111.     If numeric = "A+" Then '                Set allowed alpha numeric and extra characters
  112.         ipb.valid_str = str1 + str2 + str3 'Valid alpha/numeric and extra characters
  113.     End If
  114.     If numeric = "N" Then '    Set allowed numeric characters
  115.         ipb.valid_str = str2 ' Valid characters 0-9
  116.     End If
  117.     If numeric = "N+" Then '          Set numeric and associated characters.
  118.         ipb.valid_str = str2 + str4 ' Valid numeric and associated characters
  119.     End If
  120.  
  121.     '---Set mask option
  122.     ' ""  Default no mask
  123.     ' "A" Password mask asterisk
  124.     ' "B" Password mask Bullet
  125.     ipb.pw_mask = FALSE '                  Reset flag, disable password mask
  126.     ipb.pw_bullet = FALSE '                Reset bullet flag
  127.  
  128.     If pwMask = "A" Or pwMask = "B" Then ' Mask required
  129.         ipb.pw_mask = TRUE '               Set flag, mask required
  130.         If pwMask = "B" Then '             Bullet required
  131.             ipb.pw_bullet = TRUE '         Set bullet flag
  132.         End If
  133.     End If
  134.  
  135.     '---Get user input string
  136.     ipb_UserInput '              Run UserInput, data entered saved in buffer ipb.buf
  137.     InputBoxM = ipb_get_string ' Extract data from ipb.buf return string
  138.  
  139. '---Function Extract data from ipb.buf return input string
  140. Function ipb_get_string$ ()
  141.     Dim As String a
  142.  
  143.     'Extract string from buf
  144.     a = _Trim$(ipb.buf) '                  Remove spaces. Buffer contains a null terminated
  145.     a = Left$(a, InStr(a, Chr$(0)) - 1) '  string. Find position of null and extract
  146.     ipb.buf = "" '                         characters upto this null character. Clear buffer
  147.  
  148.     ipb_get_string = a 'Return clean string
  149.      
  150. '===Main Sub ===========================
  151. Sub ipb_UserInput
  152.     '--Constants
  153.     Const FALSE = 0
  154.     Const TRUE = Not FALSE
  155.  
  156.     Const IDC_ARROW = &H7F00
  157.     Const COLOR_WINDOW = 5
  158.      
  159.     Const WS_OVERLAPPED = 0
  160.     Const WS_CAPTION = &H00C00000
  161.     Const WS_SYSMENU = &H00080000
  162.     Const WS_VISIBLE = &H10000000
  163.     Const WS_CHILD = &H40000000
  164.     Const WS_TABSTOP = &H00010000
  165.     Const WS_EX_CLIENTEDGE = &H00000200
  166.     Const BS_PUSHBUTTON = 0
  167.     Const CW_USEDEFAULT = &H80000000
  168.     Const SW_SHOWDEFAULT = &HA
  169.  
  170.     Const ES_LEFT = 0
  171.     Const ES_NUMBER = &H2000
  172.  
  173.     Const WS_OVERLAPPEDWINDOW = WS_OVERLAPPED Or WS_CAPTION
  174.  
  175.     '--Types
  176.     Type POINT
  177.         As Long x
  178.         As Long y
  179.     End Type
  180.  
  181.     Type MSG
  182.         As _Offset hwnd
  183.         As _Unsigned Long message
  184.         As _Unsigned _Offset wParam 'unsigned pointer sized integer
  185.         As _Offset lParam '          pointer sized integer
  186.         As _Unsigned Long time
  187.         As POINT pt
  188.     End Type
  189.  
  190.     Type WNDCLASSA
  191.         As _Unsigned Long style
  192.         $If 64BIT Then
  193.             As String * 4 padding
  194.         $End If
  195.         As _Offset lpfnWndProc
  196.         As Long cbClsExtra, cbWndExtra
  197.         As _Offset hInstance, hIcon, hCursor, hbrBackground, lpszMenuName, lpszClassName
  198.     End Type
  199.  
  200.     '--Libaries
  201.  
  202.    
  203.     Declare Library "input_box_WIN"
  204.         Function GetWindowProc%& () 'Windows procedure address
  205.         '***Subclassing
  206.         Function GetSubEdit%& () '   Edit procedure address
  207.         '***End Subclassing
  208.     End Declare
  209.  
  210.     '***Subclassing
  211.         Function SetWindowLongPtr& Alias "SetWindowLongPtrA" (ByVal hwnd As _Offset, Byval nIndex As Long, Byval dwNewLong As Long)
  212.     End Declare
  213.     '***End Subclassing
  214.  
  215.     '  Declare CustomType Library
  216.     Declare Dynamic Library "user32"
  217.         Function CallWindowProc& Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, Byval hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  218.         Function SendMessageA%& (ByVal hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  219.         Function DefWindowProcA%& (ByVal hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  220.         Sub PostQuitMessage (ByVal nExitCode As Long)
  221.         Function LoadCursorW%& (ByVal hInstance As _Offset, Byval lpCursorName As _Offset)
  222.         Function RegisterClassA~% (ByVal lpWndClass As _Offset)
  223.         Function CreateWindowExA%& (ByVal dwExStyle As Long, Byval lpClassName As _Offset, Byval lpWindowName As _Offset, Byval dwStyle As Long, Byval X As Long, Byval Y As Long, Byval nWidth As Long, Byval nHeight As Long, Byval hWndParent As _Offset, Byval hMenu As _Offset, Byval hInstance As _Offset, Byval lpParam As _Offset)
  224.         Function ShowWindow& (ByVal hWnd As _Offset, Byval nCmdShow As Long)
  225.         Function UpdateWindow& (ByVal hWnd As _Offset)
  226.         Function GetMessageA% (ByVal lpMsg As _Offset, Byval hWnd As _Offset, Byval wMsgFilterMin As _Unsigned Long, Byval wMsgFilterMax As _Unsigned Long)
  227.         Function TranslateMessage& (ByVal lpMsg As _Offset)
  228.         Function DispatchMessageA%& (ByVal lpmsg As _Offset)
  229.         Sub DestroyWindow (ByVal hWnd As _Offset)
  230.         Function PostMessageA%& (ByVal hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  231.         Function SetFocus& (ByVal hWnd As _Offset)
  232.         Function GetWindowLongA& (ByVal hwnd As _Offset, Byval nIndex As Long)
  233.         Function SetWindowPos& (ByVal hWnd As _Offset, Byval hWndInsertAfter As _Offset, Byval X As Integer, Byval Y As Integer, Byval cx As Integer, Byval cy As Integer, Byval uFlags As _Offset)
  234.         Function SendMessageW%& (ByVal hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  235.         '     Function SetWindowLongA& (ByVal hwnd As _Offset, Byval nIndex As Long, Byval dwNewLong As Long)
  236.         Sub MessageBeep (ByVal alert As _Unsigned Long)
  237.     End Declare
  238.  
  239.     Declare Dynamic Library "kernel32"
  240.         Function GetModuleHandleA%& (ByVal lpModuleName%&)
  241.         Function GetLastError~& ()
  242.     End Declare
  243.     '--End Libaries
  244.  
  245.  
  246.     '--Variables
  247.     Static registered As Integer 'Variables initialized to 0 (false) hence not registered. Value retained between functtion calls
  248.  
  249.     Dim hi As _Offset '   Handle to application instance
  250.     Dim wc As WNDCLASSA ' define wc as WNDCLASSEX structure
  251.     Dim msg As MSG
  252.  
  253.     Dim dummyL As Long '   Dummy variable
  254.     Dim dummyO As _Offset 'Dummy variable
  255.     Dim t0 As String '       Type of control
  256.     Dim t1 As String '       Title or controls text
  257.  
  258.     Dim MainClassName As String * 5
  259.     MainClassName = "main" + Chr$(0)
  260.  
  261.     Dim CrLf As String * 2 '     define as 2 byte STRING
  262.     CrLf = Chr$(13) + Chr$(10) ' carriage return and line feed
  263.  
  264.     Dim As String className '               Variable className stores name of our window class
  265.     className = "myWindowClass" + Chr$(0) ' Used in wc. which in turn is used to register window class with the system.
  266.  
  267.     hi = GetModuleHandleA(0) 'Handle to application instance
  268.  
  269.     '---Step 1: Registering the Window Class
  270.     'Fill out the members of WNDCLASSEX structure (wc) and call RegisterClassA
  271.  
  272.     wc.style = 0 '                            Class Styles (CS_*), not Window Styles (WS_*) This is usually be set to 0.
  273.     wc.lpfnWndProc = GetWindowProc '          Pointer to the window procedure for this window class. (see WIN.h)
  274.     wc.cbClsExtra = 0 '                       Amount of extra data allocated for this class in memory. Usually 0.
  275.     wc.cbWndExtra = 0 '                       Amount of extra data allocated in memory per window of this type. Usually 0.
  276.     wc.hInstance = hi '                       Handle to application instance .
  277.     wc.hIcon = 0 '                            Large (usually 32x32) icon shown when the user presses Alt+Tab. Set to 0
  278.     wc.hCursor = LoadCursorW(0, IDC_ARROW) '  Cursor that will be displayed over our window.
  279.     wc.hbrBackground = COLOR_WINDOW 'was +1   Background Brush to set the color of our window. '
  280.     wc.lpszMenuName = 0 '                     Name of a menu resource to use for the windows with this class.
  281.     wc.lpszClassName = _Offset(className) '   Name to identify the class with.
  282.  
  283.     If Not registered Then '   First time in funcion OK to register.
  284.         If RegisterClassA(_Offset(wc)) = 0 Then
  285.             Print "RegisterClassA failed:"; GetLastError
  286.             End
  287.         End If
  288.         registered = TRUE ' Class was registered
  289.     End If
  290.  
  291.     '--Step 2: Creating the Windows
  292.     'After registering the class, create a window with it using CreateWindowExA.
  293.  
  294.     'Note: A visible un-owned window gets a taskbar button. To hide the inputbox window taskbar button
  295.     'make the inputbox owned by our main applicationusing using  _WindowHandle instead of 0'
  296.     t1 = ipb.caption_text + Chr$(0) 'Window title
  297.     ipb.hw = CreateWindowExA(0, _Offset(className), _Offset(t1), WS_OVERLAPPEDWINDOW, ipb.x, ipb.y, 358, 130, _WindowHandle, 0, hi, 0): If 0 = ipb.hw Then System
  298.  
  299.     'Controls are just child windows. They have a procedure, a class etc... that is registered by the system.
  300.  
  301.     'Label
  302.     t0 = "STATIC" + Chr$(0) '        Window control is STATIC predefined class
  303.     t1 = ipb.prompt_text + Chr$(0) ' Label text
  304.     ipb.hwLabel = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_VISIBLE Or WS_CHILD, 9, 5, 372, 16, ipb.hw, 0, hi, 0): If 0 = ipb.hwLabel Then System
  305.  
  306.  
  307.     'OK Button 0
  308.     t0 = "BUTTON" + Chr$(0) '   Window control is BUTTON predefined class
  309.     t1 = ipb.button0_text + Chr$(0)
  310.     ipb.hwb0 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_TABSTOP Or WS_VISIBLE Or WS_CHILD Or BS_PUSHBUTTON, 175, 65, 80, 23, ipb.hw, 0, hi, 0): If 0 = ipb.hwb0 Then System
  311.  
  312.     'Cancel button 1
  313.     t1 = ipb.button1_text + Chr$(0)
  314.     ipb.hwb1 = CreateWindowExA(0, _Offset(t0), _Offset(t1), WS_TABSTOP Or WS_VISIBLE Or WS_CHILD Or BS_PUSHBUTTON, 262, 65, 80, 23, ipb.hw, 0, hi, 0): If 0 = ipb.hwb1 Then System
  315.  
  316.     'Edit control
  317.     t0 = "EDIT" + Chr$(0)
  318.     '    t1 = "This is a edit control." + Chr$(0)
  319.     t1 = "" + Chr$(0)
  320.     ipb.hwe = CreateWindowExA(WS_EX_CLIENTEDGE, _Offset(t0), _Offset(t1), WS_VISIBLE Or WS_CHILD Or ES_LEFT, 12, 30, 330, 26, ipb.hw, 0, hi, 0): If 0 = ipb.hwe Then System
  321.  
  322.     '---Set character length
  323.     Const EM_LIMITTEXT = &H00C5
  324.     dummyO = SendMessageA(ipb.hwe, EM_LIMITTEXT, ipb.max_length, 0) 'Send message maxcharacters 8
  325.  
  326.     '----Enable and configure password mask.
  327.     'Note: The bullet is Unicode (9679 or 0x25CF ) use  SendMessageW. Use SendMessageA for old Asterisk (42)
  328.     Const EM_SETPASSWORDCHAR = &HCC
  329.     If ipb.pw_mask Then 'Input Mask required
  330.         If ipb.pw_bullet Then 'Set bullet
  331.             dummyO = SendMessageW(ipb.hwe, EM_SETPASSWORDCHAR, 9679, 0) 'Set bullet password mask
  332.         Else 'Standard *
  333.             dummyO = SendMessageA(ipb.hwe, EM_SETPASSWORDCHAR, 42, 0) 'Set Asterisk default mask
  334.         End If
  335.     Else 'Mask not required
  336.         dummyO = SendMessageA(ipb.hwe, EM_SETPASSWORDCHAR, 0, 0) '  Turn password mask off
  337.         ' dummyO = SendMessageW(ipb.hwe, EM_SETPASSWORDCHAR, 0, 0) '   Turn password mask off
  338.     End If
  339.  
  340.     '*****Subclassing
  341.     Const GWLP_WNDPROC = -4 ' Sets a new address for the window procedure
  342.     OldWindowProc = SetWindowLongPtr(ipb.hwe, GWLP_WNDPROC, ConvertOffset(GetSubEdit)) ' set your custom procedure
  343.     '*****End Subclassing
  344.  
  345.     'Display and Update window to ensure it has properly redrawn itself on the screen.
  346.     dummyL = ShowWindow(ipb.hw, SW_SHOWDEFAULT)
  347.     dummyL = UpdateWindow(ipb.hw)
  348.  
  349.     ' Force window to top and select with screen click
  350.     Const HWND_TOPMOST = -1 '      window above all others no focus unless active
  351.     Const SWP_NOSIZE = &H0001 '    ignores cx and cy size parameters
  352.     Const SWP_NOACTIVATE = &H0010 'does not activate window
  353.     dummyL = SetWindowPos(ipb.hw, HWND_TOPMOST, ipb.x, ipb.y, 0, 0, SWP_NOSIZE Or SWP_NOACTIVATE) 'force to top
  354.     _ScreenClick ipb.x + 160, ipb.y + 96 'Force focus and move cursor to left of ok button
  355.  
  356.     '-- Step 3: The Message Loop
  357.     While GetMessageA(_Offset(msg), 0, 0, 0) > 0 ' gets a message from our application's message queue.
  358.         dummyL = TranslateMessage(_Offset(msg)) '  performs some additional processing on keyboard events
  359.         dummyO = DispatchMessageA(_Offset(msg)) '  sends the message out to the window that the message was sent to
  360.     Wend
  361. '===End main function ===========================
  362.      
  363.      
  364. '-- Step 4: the Window Procedure
  365. Function WindowProc%& (hWnd As _Offset, uMsg As _Unsigned Long, wParam As _Unsigned _Offset, lParam As _Offset)
  366.     Const WM_CREATE = &H0001
  367.     Const WM_CLOSE = &H0010
  368.     Const WM_DESTROY = 2
  369.     Const WM_COMMAND = &H0111
  370.     Const BN_CLICKED = 0
  371.     Const WM_GETTEXT = &H000D
  372.     Const WM_SETFOCUS = &H0007
  373.     Dim dummyO As _Offset 'Dummy variable
  374.     Dim dummyL As Long '   Dummy variable
  375.  
  376.     Select Case uMsg
  377.  
  378.         Case WM_CLOSE
  379.             DestroyWindow (hWnd) 'Destroy window and child windows
  380.             WindowProc = 0
  381.  
  382.         Case WM_DESTROY
  383.             PostQuitMessage 0 ' Want to exit the program
  384.             WindowProc = 0
  385.  
  386.         Case WM_SETFOCUS
  387.             dummyL = SetFocus(ipb.hwe) 'Set Edit control focus
  388.             WindowProc = 0
  389.  
  390.         Case WM_COMMAND
  391.             '==============
  392.             If wParam = BN_CLICKED Then
  393.                 Select Case lParam
  394.                     'A button was clicked test each one
  395.                     '---Sandard buttons---
  396.                     Case ipb.hwb0 'OK button
  397.                         'Print "Button 0 pressed OK"
  398.                         'Get input text and copy to buffer (buf)
  399.                         dummyO = SendMessageA(ipb.hwe, WM_GETTEXT, Len(ipb.buf), _Offset(ipb.buf))
  400.                         'Print Len(buf)
  401.                         dummyO = PostMessageA(hWnd, WM_CLOSE, 0, 0) 'Close
  402.                         WindowProc = 0
  403.  
  404.                     Case ipb.hwb1 'Cancel button
  405.                         'Print "Button 1 pressed Cancel"
  406.                         ipb.buf = "" 'reset zero-length string ("").
  407.                         dummyO = PostMessageA(hWnd, WM_CLOSE, 0, 0) 'Close
  408.                         WindowProc = 0
  409.                         '---End standard buttons---
  410.                 End Select
  411.             Else
  412.                 'Not our message send back to system for processing
  413.                 WindowProc = DefWindowProcA(hWnd, uMsg, wParam, lParam)
  414.             End If
  415.             '=================
  416.             WindowProc = 0
  417.  
  418.         Case Else
  419.             'Not our message send back to system for processing
  420.             WindowProc = DefWindowProcA(hWnd, uMsg, wParam, lParam)
  421.     End Select
  422. '######--END INPUT BOX FUNCTIONS and SUBS--##################################
  423.      
  424. 'Ref https://www.qb64.org/forum/index.php?topic=1553.msg108409#msg108409
  425. 'Ref https://www.qb64.org/forum/index.php?topic=2905.msg121660#msg121660
  426.  
  427. Function ConvertOffset&& (value As _Offset)
  428.     Dim m As _MEM 'Define a memblock
  429.     m = _Mem(value) 'Point it to use value
  430.     $If 64BIT Then
  431.         Dim temp As _Integer64
  432.         'On 64 bit OSes, an OFFSET is 8 bytes in size.  We can put it directly into an Integer64
  433.         _MemGet m, m.OFFSET, temp
  434.         ConvertOffset = temp
  435.     $Else
  436.         Dim temp As Long
  437.         'However, on 32 bit OSes, an OFFSET is only 4 bytes.  We need to put it into a LONG variable first
  438.         _MemGet m, m.OFFSET, temp 'Like this
  439.         ConvertOffset = temp 'And then assign that long value to ConvertOffset&&
  440.     $End If
  441.     _MemFree m 'Free the memblock
  442.  
  443. '*****Subclass function
  444. Function SubEdit%& (hWnd As _Offset, uMsg As _Unsigned Long, wParam As _Unsigned _Offset, lParam As _Offset)
  445.     Const FALSE = 0
  446.     Const TRUE = Not FALSE
  447.     Const WM_NCDESTROY = &H82
  448.     Const GWLP_WNDPROC = -4 ' Sets a new address for the window procedure
  449.     Const WM_CONTEXTMENU = 123
  450.     Const WM_CHAR = 258
  451.     Const VK_RETURN = &H000D
  452.     Const BM_CLICK = 245
  453.     Const MB_ICONWARNING = &H30
  454.  
  455.     Dim processed As Integer 'Key valid and processed
  456.     Dim dummyL As Long '      Dummy variable
  457.     Dim dummyO As _Offset '   Dummy variable
  458.     Dim ChrValid As Integer ' Character is valid
  459.     Dim i As Integer
  460.  
  461.     'Set initial condition
  462.     processed = FALSE 'Set initial value. No key processed
  463.  
  464.     'If we're being destroyed, restore the original WindowProc.
  465.     '*****Subclassing
  466.     If uMsg = WM_NCDESTROY Then
  467.         dummyL = SetWindowLongPtr(hWnd, GWLP_WNDPROC, OldWindowProc)
  468.     End If
  469.     '*****End Subclassing
  470.  
  471.     'Disable context menu popup. Prevents a paste operation
  472.     If uMsg = WM_CONTEXTMENU Then
  473.         processed = TRUE '   Key processed nothing elese to do
  474.     End If
  475.  
  476.     'Disable Ctrl+V   Prevents a paste operation
  477.     If uMsg = WM_CHAR And wParam = 22 Then
  478.         processed = TRUE '   Key processed nothing elese to do
  479.     End If
  480.  
  481.     'Disable Enter key. Prevents anoying beep. Force enter to produce OK button click
  482.     'Pressing the enter key with Edit Control  in focus.
  483.     'Default behavior is to produce an annoying beep this is
  484.     'because enter is an invalid key for this control.
  485.  
  486.     If uMsg = WM_CHAR And wParam = VK_RETURN Then 'Enter key pressed
  487.         dummyO = SendMessageA(ipb.hwb0, BM_CLICK, 0, 0) ' Send message (button click) to OK button
  488.         processed = TRUE '   Key processed nothing elese to do
  489.     End If
  490.  
  491.     'Valid character section all others invalid
  492.     If uMsg = WM_CHAR Then 'There is a character to process
  493.         'Print wParam
  494.  
  495.         ChrValid = FALSE '                Set initial value
  496.         For i = 1 To Len(ipb.valid_str) ' Scan valid characters and backspace=8
  497.             If wParam = Asc(Mid$(ipb.valid_str, i, 1)) Or wParam = 8 Then
  498.                 ChrValid = TRUE ' Key in valid range. Allow default processing
  499.             End If
  500.         Next
  501.  
  502.         If Not ChrValid Then ' Invalid character remove by setting processed
  503.             processed = TRUE ' true flag. Forceses return 0 for invalid keys'
  504.             'Alert user.
  505.             If Not (wParam = VK_RETURN) Then ' Note: Return key is valid.
  506.                 MessageBeep MB_ICONWARNING '   For invalid characters
  507.             End If '                           create a "ding" to alert user.
  508.         End If
  509.     End If
  510.     'End valid character
  511.  
  512.     'Set return value
  513.     If processed Then 'A key was processed
  514.         SubEdit = 0 '  Return 0 no further processing required
  515.     Else '             No key processed pass onto default  processing
  516.         '*****Subclassing
  517.         SubEdit = CallWindowProc(OldWindowProc, hWnd, uMsg, wParam, lParam)
  518.         '*****End Subclassing
  519.     End If
  520.  
  521. '*****End Subclass functionn
  522. '###_start_BM_inputbox
  523.  
input_box_WIN.h
Code: QB64: [Select]
  1. ptrszint FUNC_WINDOWPROC(ptrszint*_FUNC_WINDOWPROC_OFFSET_HWND,uint32*_FUNC_WINDOWPROC_ULONG_UMSG,uptrszint*_FUNC_WINDOWPROC_UOFFSET_WPARAM,ptrszint*_FUNC_WINDOWPROC_OFFSET_LPARAM);
  2.  
  3. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  4.  return FUNC_WINDOWPROC((ptrszint *) (& hwnd), & uMsg, & wParam, (ptrszint *) (& lParam));
  5. }
  6.  
  7. void * GetWindowProc() {
  8.  return (void *) WindowProc;
  9. }
  10.  
  11.  
  12. ptrszint FUNC_SUBEDIT(ptrszint*_FUNC_SUBEDIT_OFFSET_HWND,uint32*_FUNC_SUBEDIT_ULONG_UMSG,uptrszint*_FUNC_SUBEDIT_UOFFSET_WPARAM,ptrszint*_FUNC_SUBEDIT_OFFSET_LPARAM);
  13.  
  14. LRESULT CALLBACK SubEdit(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  15.  return FUNC_SUBEDIT((ptrszint *) (& hwnd), & uMsg, & wParam, (ptrszint *) (& lParam));
  16. }
  17.  
  18. void * GetSubEdit() {
  19.  return (void *) SubEdit;
  20. }
  21.  

Compile input_box_example.bas


9
Hi Fellippe and Dav
Wait for the screen to exists is the solution.
It explains why some programs worked and other failed.

DO: LOOP UNTIL _SCREENEXISTS

Many thanks to you both.

10
The following code fails on the new development builds:
Code: QB64: [Select]
  1. Print "hwnd = "; _WindowHandle
_WindowHandle returns a 0 and not a handle as expected.

The following code fails on the dev builds however works fine on stable builds (1.5 x32 x64 3043116) note added a test line:

Ref: https://www.qb64.org/wiki/Windows_Libraries#Borderless_Window

Code: QB64: [Select]
  1. '============
  2. 'NOBORDER.BAS
  3. '============
  4.  
  5.     FUNCTION FindWindow& (BYVAL ClassName AS _OFFSET, WindowName$)
  6.  
  7.     FUNCTION GetWindowLongA& (BYVAL hwnd AS LONG, BYVAL nIndex AS LONG)
  8.     FUNCTION SetWindowLongA& (BYVAL hwnd AS LONG, BYVAL nIndex AS LONG, BYVAL dwNewLong AS LONG)
  9.     FUNCTION SetWindowPos& (BYVAL hwnd AS LONG, BYVAL hWndInsertAfter AS LONG, BYVAL x AS LONG, BYVAL y AS LONG, BYVAL cx AS LONG, BYVAL cy AS LONG, BYVAL wFlags AS LONG)
  10.  
  11. GWL_STYLE = -16
  12. WS_BORDER = &H800000
  13.  
  14. _TITLE "No Border"
  15. hwnd& = _WINDOWHANDLE 'FindWindow(0, "No Border" + CHR$(0))
  16. Print "hwnd = "; _WindowHandle '<<<<<<< Test line
  17.  
  18. PRINT "Press any key for no border...": A$ = INPUT$(1)
  19.  
  20. winstyle& = GetWindowLongA&(hwnd&, GWL_STYLE)
  21. a& = SetWindowLongA&(hwnd&, GWL_STYLE, winstyle& AND NOT WS_BORDER)
  22. a& = SetWindowPos&(hwnd&, 0, 0, 0, 0, 0, 39)
  23.  
  24. PRINT "Press any key to get back border...": SLEEP
  25.  
  26. winstyle& = GetWindowLongA&(hwnd&, GWL_STYLE)
  27. a& = SetWindowLongA&(hwnd&, GWL_STYLE, winstyle& OR WS_BORDER)
  28. a& = SetWindowPos&(hwnd&, 0, 0, 0, 0, 0, 39)
  29.  
  30. PRINT "The end"
  31.  
QB64 Development Builds:
QB64x32 2.0 049499c
QB64x64  2.0 049499c

PC spec as follows:  Windows 8.1,  Processor Intel(R) Core(TM) i3-3217U CPU 1.8 GHz, RAM 4GB, 64-bit

11
The following function fails on dev build QB64x64 edb4d40
Error message:  Incorrect number of arguments passed to function on line 14
Note: Worked fine on previous builds

Ref: https://www.qb64.org/forum/index.php?topic=1015.msg102131#msg102131
Code: QB64: [Select]
  1. m = _Mem(x)
  2. Print m.OFFSET
  3. Print ConvertOffset(m.OFFSET)
  4.  
  5.  
  6. Function ConvertOffset&& (value As _Offset)
  7.     Dim m As _MEM 'Define a memblock
  8.     m = _Mem(value) 'Point it to use value
  9.     $If 64BIT Then
  10.         'On 64 bit OSes, an OFFSET is 8 bytes in size.  We can put it directly into an Integer64
  11.     _MEMGET m, m.OFFSET, ConvertOffset&& 'Get the contents of the memblock and put the values there directly into ConvertOffset&&
  12.  
  13.     'However, on 32 bit OSes, an OFFSET is only 4 bytes.  We need to put it into a LONG variable first
  14.     _MEMGET m, m.OFFSET, temp& 'Like this
  15.     ConvertOffset&& = temp& 'And then assign that long value to ConvertOffset&&
  16. _MEMFREE m 'Free the memblock
  17.  

12
Previous code that failed to compile now compiles with the new dev builds, that really is excellent, thank you Spriggsy and Fellippe.

For testing I used a program that is difficult to debug, it has a new window process and uses subclassing.
I had a few teething problems with the debugger mainly setting inappropriate break points and incorrect use of menu options.
That said I was surprised how stable QB64 debug is. It really is turning into an indispensable tool keep up the great work.
 
QB64 Development Builds:
QB64x32 1.6 d651f37
QB64x64 1.6 d651f37

PC spec as follows:  Windows 8.1,  Processor Intel(R) Core(TM) i3-3217U CPU 1.8 GHz, RAM 4GB, 64-bit

13
Hi Spriggsy and Fellippe thank you both  for the feedback.  Spriggsy I do understand it is preferential to use  Declare CustomType Library instead of  Declare Dynamic Library.
That said your solution if successful will only add to the flexibility of QB64. I cant wait to test the proposed solution.

"Let me know if you need any help or come across any further compilation errors when using external functions." offer most appreciated I am sure  at a latter date will be required thank you.

14
The following code compiles and runs on both 32 and 64 dev versions (Note no $Debug  meta command).
Code: QB64: [Select]
  1. 'Desktop Size
  2. 'Returns the Left, Top, Right and Bottom coordinates of the current desktop area.
  3. 'https://www.qb64.org/wiki/Windows_Libraries
  4.  
  5.     Function SystemParametersInfoW& (ByVal uiAction~&, Byval uiParam~&, Byval pvParam%&, Byval fWinlni~&)
  6.  
  7. Const SPI_GETWORKAREA = &H30
  8.  
  9. Type RECT
  10.     left As Long
  11.     top As Long
  12.     right As Long
  13.     bottom As Long
  14. Dim Rec As RECT
  15.  
  16. If 0 = SystemParametersInfoW(SPI_GETWORKAREA, 0, _Offset(Rec), 0) Then
  17.     'function failed. You may call kernel32's GetLastError for more info.
  18.     Print "failed."
  19.  
  20. Print Rec.left
  21. Print Rec.top
  22. Print Rec.right
  23. Print Rec.bottom
  24.  
After adding the $Debug meta command both dev versions fail to compile above code. Error message from compilelog.txt
Code: QB64: [Select]
  1. In file included from qbx.cpp:1099:
  2. ..\\temp\\regsf.txt:5:11: error: redefinition of 'HINSTANCE__* DLL_user32'
  3.  HINSTANCE DLL_user32=NULL;
  4.            ^~~~~~~~~~
  5. compilation terminated due to -Wfatal-errors.
  6.  
Simple solution replace Declare Dynamic Library "user32" with Declare CustomType Library
However that's not a real solution it just masks the problem.

QB64 Development Builds:
QB64x32 1.6 75939af
QB64x64 1.6 75939af

PC spec as follows:
 Windows 8.1
 Processor Intel(R) Core(TM) i3-3217U CPU 1.8 GHz
 Installed memory RAM 4GB
 System type: 64-bit Operating System, x64-based processor




15
QB64 Discussion / Re: InputBox
« on: September 11, 2021, 05:12:13 am »
Hi  Spriggsy thank you for a quick reply.  I ran your modified code in both QB64 32 and 64 bit
With the following interesting results:

1a) QB64x32 Version 1.5 Stable Release From git 3043116
After compiling there is a flicker (attempts to run and closes) .

1b) QB64x32 Version 1.6 Development Build From git ca32adf
After compiling there is a flicker (attempts to run and closes) .

2a) QB64x64 Version 1.5 Stable Release From git 3043116
The program compiles and runs however the subclass function "SubEdit" does not get called.

2b) QB64x64 Version 1.6 Development Build From git ca32adf
The program compiles and runs however the subclass function "SubEdit" does not get called.

In the pass I have seen issues when declaring libraries in QB64x32.  With my PC it seems some libraries need a specific declaration.
I regressed  library definitions as follows:
Code: QB64: [Select]
  1.  Declare Library "WIN2"
  2.         Function GetWindowProc%& () 'Windows procedure
  3.         Function GetSubEdit%& () 'Edit procedure
  4.     End Declare
  5.  
  6.     '   Declare CustomType Library
  7.     '       Function SetWindowLongPtr& Alias "SetWindowLongPtrA" (ByVal hwnd As _Offset, Byval nIndex As Long, Byval dwNewLong As Long)
  8.     '       Function GetWindowLongPtr& (ByVal hwnd As _Offset, Byval nIndex As Long)
  9.     '     Function CallWindowProc& Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, Byval hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  10.     '   End Declare
  11.  
  12.     Declare Dynamic Library "user32"
  13.         Function CallWindowProc& Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, Byval hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  14.         Function SendMessageA%& (ByVal hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  15.         Function DefWindowProcA%& (ByVal hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  16.         Sub PostQuitMessage (ByVal nExitCode As Long)
  17.         Function LoadCursorW%& (ByVal hInstance As _Offset, Byval lpCursorName As _Offset)
  18.         Function RegisterClassA~% (ByVal lpWndClass As _Offset)
  19.         Function CreateWindowExA%& (ByVal dwExStyle As Long, Byval lpClassName As _Offset, Byval lpWindowName As _Offset, Byval dwStyle As Long, Byval X As Long, Byval Y As Long, Byval nWidth As Long, Byval nHeight As Long, Byval hWndParent As _Offset, Byval hMenu As _Offset, Byval hInstance As _Offset, Byval lpParam As _Offset)
  20.         Function ShowWindow& (ByVal hWnd As _Offset, Byval nCmdShow As Long)
  21.         Function UpdateWindow& (ByVal hWnd As _Offset)
  22.         Function GetMessageA% (ByVal lpMsg As _Offset, Byval hWnd As _Offset, Byval wMsgFilterMin As _Unsigned Long, Byval wMsgFilterMax As _Unsigned Long)
  23.         Function TranslateMessage& (ByVal lpMsg As _Offset)
  24.         Function DispatchMessageA%& (ByVal lpmsg As _Offset)
  25.         Sub DestroyWindow (ByVal hWnd As _Offset)
  26.         Function PostMessageA%& (ByVal hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
  27.         Function SetFocus& (ByVal hWnd As _Offset)
  28.         Function GetWindowLongA& (ByVal hwnd As _Offset, Byval nIndex As Long)
  29.         Function SetWindowLongA& (ByVal hwnd As _Offset, Byval nIndex As Long, Byval dwNewLong As Long)
  30.     End Declare
  31.  
  32.     Declare Dynamic Library "kernel32"
  33.         Function GetModuleHandleA%& (ByVal lpModuleName%&)
  34.         Function GetLastError~& ()
  35.     End Declare
  36.  

Ran the new code with the following results:

1an) QB64x32 Version 1.5 Stable Release From git 3043116
Works as expected.
Test: At the first input popup enter 123qwer
Result: 123 displayed

1bn) QB64x32 Version 1.6 Development Build From git ca32adf
Works as expected.

2an) QB64x64 Version 1.5 Stable Release From git 3043116
The program compiles and runs however the subclass function "SubEdit" does not get called.
Test: At the first input popup enter 123qwer
Result: 123qwer displayed - function "SubEdit" not called.

2bn) QB64x64 Version 1.6 Development Build From git ca32adf
The program compiles and runs however the subclass function "SubEdit" does not get called.

I just found this https://www.qb64.org/wiki/DECLARE_DYNAMIC_LIBRARY
"Note: SUB procedures using CUSTOMTYPE LIBRARY API procedures inside may error. Try DYNAMIC with "KERNEL32"."
May explain what I observed with the above QB64x32

Back to the original problem how to run the  subclass function "SubEdit" on QB64x64

Note: My PC spec as follows:
 Windows 8.1
 Processor Intel(R) Core(TM) i3-3217U CPU 1.8 GHz
 Installed memory RAM 4GB
 System type: 64-bit Operating System, x64-based processor

P.S. I liked the bonus, $VERSIONINFO comment. Works fine in the dev builds.


Pages: [1] 2