Author Topic: Windows buttons for 32 and 64 bit IDE  (Read 3707 times)

0 Members and 1 Guest are viewing this topic.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Windows buttons for 32 and 64 bit IDE
« on: November 06, 2020, 01:57:09 pm »
Hi, yesterday Dav gave us an amazing code to run some  button elements. Its version only worked in 32 bits. I wrote upgrade, so now it works for both 32 and 64 bit.

Code: QB64: [Select]
  1. 'DEFSTR A-Z
  2.  
  3. ' public domain, michael calkins
  4. ' revision 2012 09 12
  5. ' very much experimental. I am a noob at GUI stuff, and might be doing multiple things wrong or in unideal ways.
  6. ' rough translation of:
  7. ' http://www.network54.com/Forum/613583/message/1347419042/
  8. ' with a few liberties taken.
  9.  
  10. ' not only might I be doing things wrong, but I am also not doublechecking the function declarations, type definitions, and constant values. They could be wrong.
  11.  
  12.  
  13. ' get more constants from winuser.h as needed.
  14.  
  15. CONST IDC_ARROW = &H7F00
  16. CONST COLOR_WINDOW = 5
  17.  
  18. CONST WS_OVERLAPPED = 0
  19. CONST WS_CHILD = &H40000000
  20. CONST WS_VISIBLE = &H10000000
  21. CONST WS_MAXIMIZE = &H01000000
  22. CONST WS_CAPTION = &H00C00000
  23. CONST WS_VSCROLL = &H00200000
  24. CONST WS_HSCROLL = &H00100000
  25. CONST WS_SYSMENU = &H00080000
  26. CONST WS_THICKFRAME = &H00040000
  27. CONST WS_TABSTOP = &H00010000
  28. CONST WS_MINIMIZEBOX = &H00020000
  29. CONST WS_MAXIMIZEBOX = &H00010000
  30. CONST WS_OVERLAPPEDWINDOW = WS_OVERLAPPED OR WS_CAPTION OR WS_SYSMENU OR WS_THICKFRAME OR WS_MINIMIZEBOX OR WS_MAXIMIZEBOX
  31.  
  32. CONST CW_USEDEFAULT = &H80000000&
  33.  
  34. CONST BS_PUSHBUTTON = 0
  35. CONST BS_AUTOCHECKBOX = 3
  36. CONST BS_GROUPBOX = 7
  37. CONST BS_AUTORADIOBUTTON = 9
  38. CONST BS_TEXT = 0
  39.  
  40. CONST BN_CLICKED = 0
  41.  
  42. CONST BM_GETCHECK = &HF0
  43.  
  44. CONST ES_LEFT = 0
  45. CONST ES_MULTILINE = 4
  46. CONST ES_AUTOVSCROLL = &H0040
  47. CONST ES_AUTOHSCROLL = &H0080
  48. CONST ES_WANTRETURN = &H1000
  49.  
  50. CONST WM_DESTROY = 2
  51. CONST WM_GETTEXT = &H000D
  52. CONST WM_CLOSE = &H0010
  53. CONST WM_COMMAND = &H0111
  54.  
  55. CONST SW_SHOWDEFAULT = &HA
  56.  
  57.     FUNCTION GetWindowProc%& ()
  58.  
  59.     FUNCTION SendMessageA%& (BYVAL hWnd%&, BYVAL Msg~&, BYVAL wParam~%&, BYVAL lParam%&)
  60.     FUNCTION DefWindowProcA%& (BYVAL hWnd%&, BYVAL Msg~&, BYVAL wParam~%&, BYVAL lParam%&)
  61.     SUB PostQuitMessage (BYVAL nExitCode&)
  62.     FUNCTION LoadCursorW%& (BYVAL hInstance%&, BYVAL lpCursorName%&)
  63.     FUNCTION RegisterClassA~% (BYVAL lpWndClass%&)
  64.     FUNCTION CreateWindowExA%& (BYVAL dwExStyle~&, BYVAL lpClassName%&, BYVAL lpWindowName%&, BYVAL dwStyle~&, BYVAL x&, BYVAL y&, BYVAL nWidth&, BYVAL nHeight&, BYVAL hWndParent%&, BYVAL hMenu%&, BYVAL hInstance%&, BYVAL lpParam%&)
  65.     FUNCTION ShowWindow& (BYVAL hWnd%&, BYVAL nCmdShow&)
  66.     FUNCTION UpdateWindow& (BYVAL hWnd%&)
  67.     FUNCTION GetMessageA& (BYVAL lpMsg%&, BYVAL hWnd%&, BYVAL wMsgFilterMin~&, BYVAL wMsgFilterMax~&)
  68.     FUNCTION TranslateMessage& (BYVAL lpMsg%&)
  69.     FUNCTION DispatchMessageA%& (BYVAL lpmsg%&)
  70.  
  71.     FUNCTION GetModuleHandleW%& (BYVAL lpModuleName%&)
  72.     FUNCTION GetLastError~& ()
  73.  
  74.     x AS LONG
  75.     y AS LONG
  76.  
  77. $IF 32BIT THEN
  78.     TYPE MSG
  79.         hwnd AS _OFFSET
  80.         message AS _UNSIGNED LONG
  81.         wParam AS _UNSIGNED _OFFSET 'unsigned pointer sized integer
  82.         lParam AS _OFFSET 'pointer sized integer
  83.         time AS _UNSIGNED LONG
  84.         pt AS POINT
  85.     END TYPE
  86.  
  87.     TYPE WNDCLASSA
  88.         style AS _UNSIGNED LONG
  89.         lpfnWndProc AS _OFFSET
  90.         cbClsExtra AS LONG
  91.         cbWndExtra AS LONG
  92.         hInstance AS _OFFSET
  93.         hIcon AS _OFFSET
  94.         hCursor AS _OFFSET
  95.         hbrBackground AS _OFFSET
  96.         lpszMenuName AS _OFFSET
  97.         lpszClassName AS _OFFSET
  98.     END TYPE
  99.     TYPE MSG
  100.     hwnd AS _OFFSET
  101.     message AS _OFFSET
  102.     wParam AS _OFFSET 'unsigned pointer sized integer
  103.     lParam AS _OFFSET 'pointer sized integer
  104.     time AS _INTEGER64
  105.     pt AS POINT
  106.     END TYPE
  107.  
  108.     TYPE WNDCLASSA
  109.     style AS _INTEGER64
  110.     lpfnWndProc AS _OFFSET
  111.     cbClsExtra AS LONG
  112.     cbWndExtra AS LONG
  113.     hInstance AS _OFFSET
  114.     hIcon AS _OFFSET
  115.     hCursor AS _OFFSET
  116.     hbrBackground AS _OFFSET
  117.     lpszMenuName AS _OFFSET
  118.     lpszClassName AS _OFFSET
  119.     END TYPE
  120.  
  121.  
  122.  
  123. DIM SHARED wc AS WNDCLASSA
  124. DIM SHARED msg AS MSG
  125.  
  126. DIM SHARED buf AS STRING * 4096
  127.  
  128. DIM SHARED discardb AS LONG
  129. DIM SHARED discardp AS _OFFSET
  130.  
  131. DIM SHARED MainClassName AS STRING * 5
  132. MainClassName = "main" + CHR$(0)
  133. DIM SHARED crlf AS STRING * 2
  134. crlf = MKI$(&HA0D)
  135.  
  136. hi = GetModuleHandleW(0)
  137.  
  138. wc.style = 0
  139. wc.lpfnWndProc = GetWindowProc
  140. wc.cbClsExtra = 0
  141. wc.cbWndExtra = 0
  142. wc.hInstance = hi
  143. wc.hIcon = 0
  144. wc.hCursor = LoadCursorW(0, IDC_ARROW)
  145. wc.hbrBackground = COLOR_WINDOW + 1
  146. wc.lpszMenuName = 0
  147. wc.lpszClassName = _OFFSET(MainClassName)
  148.  
  149. at = RegisterClassA(_OFFSET(wc)): IF 0 = at THEN SYSTEM
  150.  
  151. t1 = "title" + CHR$(0)
  152. hw = CreateWindowExA(0, at AND &HFFFF~&, _OFFSET(t1), WS_HSCROLL OR WS_OVERLAPPEDWINDOW OR WS_VSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hi, 0): IF 0 = hw THEN SYSTEM
  153. t0 = "BUTTON" + CHR$(0)
  154. t1 = "Button 0" + CHR$(0)
  155. hwb0 = CreateWindowExA(0, _OFFSET(t0), _OFFSET(t1), WS_TABSTOP OR WS_VISIBLE OR WS_CHILD OR BS_PUSHBUTTON OR BS_TEXT, 10, 10, 150, 40, hw, 0, hi, 0): IF 0 = hw THEN SYSTEM
  156. t1 = "Button 1" + CHR$(0)
  157. hwb1 = CreateWindowExA(0, _OFFSET(t0), _OFFSET(t1), WS_TABSTOP OR WS_VISIBLE OR WS_CHILD OR BS_PUSHBUTTON OR BS_TEXT, 10, 60, 150, 40, hw, 0, hi, 0): IF 0 = hwb0 THEN SYSTEM
  158. t1 = "Chk box" + CHR$(0)
  159. hwcb = CreateWindowExA(0, _OFFSET(t0), _OFFSET(t1), WS_TABSTOP OR WS_VISIBLE OR WS_CHILD OR BS_AUTOCHECKBOX OR BS_TEXT, 10, 110, 150, 40, hw, 0, hi, 0): IF 0 = hwb1 THEN SYSTEM
  160. t1 = "Group box" + CHR$(0)
  161. hwgb = CreateWindowExA(0, _OFFSET(t0), _OFFSET(t1), WS_VISIBLE OR WS_CHILD OR BS_GROUPBOX OR BS_TEXT, 10, 160, 400, 80, hw, 0, hi, 0): IF 0 = hwgb THEN SYSTEM
  162. t1 = "Radio 0" + CHR$(0)
  163. hwr0 = CreateWindowExA(0, _OFFSET(t0), _OFFSET(t1), WS_TABSTOP OR WS_VISIBLE OR WS_CHILD OR BS_AUTORADIOBUTTON OR BS_TEXT, 10, 30, 150, 30, hwgb, 0, hi, 0): IF 0 = hwr0 THEN SYSTEM
  164. t1 = "Radio 1" + CHR$(0)
  165. hwr1 = CreateWindowExA(0, _OFFSET(t0), _OFFSET(t1), WS_TABSTOP OR WS_VISIBLE OR WS_CHILD OR BS_AUTORADIOBUTTON OR BS_TEXT, 210, 30, 150, 30, hwgb, 0, hi, 0): IF 0 = hwr1 THEN SYSTEM
  166. t0 = "EDIT" + CHR$(0)
  167. 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)
  168. hwe = CreateWindowExA(0, _OFFSET(t0), _OFFSET(t1), WS_TABSTOP OR WS_VISIBLE OR WS_CHILD OR ES_AUTOHSCROLL OR ES_AUTOVSCROLL OR ES_LEFT OR ES_MULTILINE OR ES_WANTRETURN, 10, 300, 400, 200, hw, 0, hi, 0): IF 0 = hwe THEN SYSTEM
  169.  
  170. discardb = ShowWindow(hw, SW_SHOWDEFAULT)
  171. discardb = UpdateWindow(hw)
  172.     bRet = GetMessageA(_OFFSET(msg), 0, 0, 0)
  173.     SELECT CASE bRet
  174.         CASE 0, -1: EXIT DO
  175.     END SELECT
  176.     discardb = TranslateMessage(_OFFSET(msg))
  177.     discardp = DispatchMessageA(_OFFSET(msg))
  178.  
  179. ' Hopefully the user is running this console program from the command prompt.
  180. ' If not, the half second delay should remind them.
  181. ' I think that Sleep is okay here, because I assume we shouldn't be getting any more messages.
  182. ' We're out of the message loop anyway...
  183.  
  184.  
  185.  
  186. FUNCTION WindowProc%& (hWnd AS _OFFSET, uMsg AS _UNSIGNED LONG, wParam AS _UNSIGNED _OFFSET, lParam AS _OFFSET)
  187.  
  188.     SELECT CASE uMsg
  189.  
  190.         CASE WM_CLOSE
  191.  
  192.             discardp = SendMessageA(hwe, WM_GETTEXT, LEN(buf), _OFFSET(buf))
  193.             PRINT: PRINT "First part of the edit control text:": PRINT
  194.             PRINT buf: PRINT
  195.             PRINT "Radio 0: 0x"; HEX$(SendMessageA(hwr0, BM_GETCHECK, 0, 0))
  196.             PRINT "Radio 1: 0x"; HEX$(SendMessageA(hwr1, BM_GETCHECK, 0, 0))
  197.  
  198.             WindowProc = DefWindowProcA(hWnd, uMsg, wParam, lParam): EXIT FUNCTION
  199.  
  200.         CASE WM_DESTROY
  201.  
  202.             PostQuitMessage 0
  203.             WindowProc = 0: EXIT FUNCTION
  204.  
  205.         CASE WM_COMMAND
  206.  
  207.             IF wParam \ &H10000 = BN_CLICKED THEN
  208.                 SELECT CASE lParam
  209.                     CASE hwb0: PRINT "Button 0 pressed"
  210.                     CASE hwb1: PRINT "Button 1 pressed"
  211.                     CASE hwcb: PRINT "Check box pressed"
  212.  
  213.                         ' The following two lines are useless, because the Group Box is getting the message, not us.
  214.                     CASE hwr0: PRINT "Radio 0 pressed"
  215.                     CASE hwr1: PRINT "Radio 1 pressed"
  216.                 END SELECT
  217.                 WindowProc = 0: EXIT FUNCTION
  218.             ELSE
  219.                 WindowProc = DefWindowProcA(hWnd, uMsg, wParam, lParam): EXIT FUNCTION
  220.             END IF
  221.  
  222.         CASE ELSE
  223.  
  224.             WindowProc = DefWindowProcA(hWnd, uMsg, wParam, lParam): EXIT FUNCTION
  225.     END SELECT
  226.  
  227.  

WIN.H file:

Code: [Select]
ptrszint FUNC_WINDOWPROC(ptrszint*_FUNC_WINDOWPROC_OFFSET_HWND,uint32*_FUNC_WINDOWPROC_ULONG_UMSG,uptrszint*_FUNC_WINDOWPROC_UOFFSET_WPARAM,ptrszint*_FUNC_WINDOWPROC_OFFSET_LPARAM);

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
 return FUNC_WINDOWPROC((ptrszint *) (& hwnd), & uMsg, & wParam, (ptrszint *) (& lParam));
}

void * GetWindowProc() {
 return (void *) WindowProc;
}



FellippeHeitor

  • Guest
Re: Windows buttons for 32 and 64 bit IDE
« Reply #1 on: November 06, 2020, 02:16:04 pm »
Thanks for the update, Petr!

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Windows buttons for 32 and 64 bit IDE
« Reply #2 on: November 06, 2020, 04:43:19 pm »
Good, Petr! 

It's working here - I'm using Win7-32bit.  I don't have a 64-bit OS to test on.

- Dav

FellippeHeitor

  • Guest
Re: Windows buttons for 32 and 64 bit IDE
« Reply #3 on: November 06, 2020, 04:52:46 pm »
In XP, if you have a file with the same name as your .exe + .manifest (like untitled.exe.manifest) with the contents below, controls will use XP's visual styles. Might work in 7.

The code above works in Win10 64bit, but the .manifest trick doesn't.

Code: [Select]
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity
    version="1.2.3.4"
    processorArchitecture="*"
    name="Company.Product.Program"
    type="win32"
  />
  <description>Program Description Here</description>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity
        type="win32"
        name="Microsoft.Windows.Common-Controls"
        version="6.0.0.0"
        publicKeyToken="6595b64144ccf1df"
        language="*"
        processorArchitecture="*"
      />
    </dependentAssembly>
  </dependency>
</assembly>

Before the .manifest:
 
Captura_de_Tela_2020-11-06_as_16.31.44.png


After the .manifest:
 
Captura_de_Tela_2020-11-06_as_16.32.04.png
« Last Edit: November 06, 2020, 05:05:47 pm by FellippeHeitor »

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Windows buttons for 32 and 64 bit IDE
« Reply #4 on: November 06, 2020, 05:59:36 pm »
Hi, Fellippe. I don't have  Windows 10 for test. Look in the SpriggsySprigs thread on Base64, below we started talking about this. Dav there gave a link to the old forum where the C source is upgraded. Try it with that. If that doesn't work, try shuffling the data types in the $ IF block. All you have to think about is the byte sum of the fields. If you replace _INTEGER64 with _OFFSET, the field length is the same (both take 8 bytes in a 64-bit system), if you replace LONG with _INTEGER64, you have an array 4 bytes longer, so you have to take 4 bytes again somewhere ( make it 4 bytes lower), otherwise it won't work.
« Last Edit: November 06, 2020, 06:02:27 pm by Petr »