GUI: piano keyboard

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
SpeedMaster
Posts: 494
Joined: 12 Nov 2016, 16:09

Re: GUI: piano keyboard

14 Apr 2018, 16:45

jeeswg wrote:- Does anybody have any good AHK links for a piano keyboard GUI? Thanks.
hello,
I think this one is the most advanced so far:
Klavier Hero 2010 by Bentschi :ugeek:
topic: http://ahkscript.org/germans/forums/vie ... php?t=6803

:!: You can resize the gui by dragging the corner

Cheers
Last edited by SpeedMaster on 19 Apr 2018, 07:39, edited 2 times in total.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI: piano keyboard

17 Apr 2018, 01:03

- Thanks SpeedMaster, this is really nice. I had searched the forums for piano scripts and hadn't found this one.
- The keys appear to be set up for a German keyboard, so I've provided a script below for people to adjust the keyboard keys as appropriate. Replace the HotkeysLine1 and HotkeysLine2 lines in the script.

Code: Select all

q:: ;prepare keys for Klavier Hero 2010 by Bentschi
HotkeysLine1X := "\azsxdcvgbhnmk,l.;/"
HotkeysLine1 := "HotkeysLine1 = "
HotkeysLine2X := "q2w3er5t6y7ui9o0p[=]"
HotkeysLine2 := "HotkeysLine2 = "
Loop, Parse, HotkeysLine1X
	HotkeysLine1 .= (A_Index=1 ? "" : ",") GetKeyVK(A_LoopField)
Loop, Parse, HotkeysLine2X
	HotkeysLine2 .= (A_Index=1 ? "" : ",") GetKeyVK(A_LoopField)
Clipboard := HotkeysLine1 "`r`n; " HotkeysLine1X "`r`n" HotkeysLine2 "`r`n; " HotkeysLine2X
MsgBox, % HotkeysLine1 "`r`n; " HotkeysLine1X "`r`n" HotkeysLine2 "`r`n; " HotkeysLine2X
return

;result:
HotkeysLine1 = 220,65,90,83,88,68,67,86,71,66,72,78,77,75,188,76,190,186,191
; \azsxdcvgbhnmk,l.;/
HotkeysLine2 = 81,50,87,51,69,82,53,84,54,89,55,85,73,57,79,48,80,219,187,221
; q2w3er5t6y7ui9o0p[=]
- The script is working, but the keyboard is only displaying for me in AutoHotkey Basic/AutoHotkey v1.1 ANSI. Here's a fix for AutoHotkey v1.1 x32 Unicode, you need to replace 'str' with 'astr' in lines that use GetProcAddress.

Code: Select all

midiOutShortMsg := DllCall("GetProcAddress", uint, WinMM_Lib, astr, "midiOutShortMsg")

SwapBuffers := DllCall("GetProcAddress", uint, hGdi32, astr, "SwapBuffers")
glClear := DllCall("GetProcAddress", uint, hOpenGL, astr, "glClear")
glViewport := DllCall("GetProcAddress", uint, hOpenGL, astr, "glViewport")
glMatrixMode := DllCall("GetProcAddress", uint, hOpenGL, astr, "glMatrixMode")
glLoadIdentity := DllCall("GetProcAddress", uint, hOpenGL, astr, "glLoadIdentity")
glOrtho := DllCall("GetProcAddress", uint, hOpenGL, astr, "glOrtho")
glVertex2f := DllCall("GetProcAddress", uint, hOpenGL, astr, "glVertex2f")
glScalef := DllCall("GetProcAddress", uint, hOpenGL, astr, "glScalef")
glTranslatef := DllCall("GetProcAddress", uint, hOpenGL, astr, "glTranslatef")
glCallList := DllCall("GetProcAddress", uint, hOpenGL, astr, "glCallList")
glPushMatrix := DllCall("GetProcAddress", uint, hOpenGL, astr, "glPushMatrix")
glPopMatrix := DllCall("GetProcAddress", uint, hOpenGL, astr, "glPopMatrix")
glColor4f := DllCall("GetProcAddress", uint, hOpenGL, astr, "glColor4f")
glEnable := DllCall("GetProcAddress", uint, hOpenGL, astr, "glEnable")
glDisable := DllCall("GetProcAddress", uint, hOpenGL, astr, "glDisable")
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
SpeedMaster
Posts: 494
Joined: 12 Nov 2016, 16:09

Re: GUI: piano keyboard

17 Apr 2018, 09:24

jeeswg wrote:I've provided a script below to adjust the keyboard keys as appropriate
Here's a fix for AutoHotkey v1.1 x32 Unicode, you need to replace 'str' with 'astr' in lines that use GetProcAddress.
Thanks for the fix. :D
I added a new link for x32 version and US keyboard (see the previous link) :thumbup:
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: GUI: piano keyboard

17 Apr 2018, 17:34

I've modded the script to use scancodes instead of virtual keys, which should allow its usage regardless of the keyboard layout, and also changed some data types for attempted compatibility with x64 systems (not tested). Anybody interested? I could post it tomorrow if this sudden cold doesn't kill me by then.
Part of my AHK work can be found here.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI: piano keyboard

17 Apr 2018, 18:02

That would be interesting Drugwash, thanks.
I've tried to correct the script to make it work in AHK v1.1 x64 also.
See TIPS FOR CONVERTING OLD SCRIPTS, here [note: includes AHK v1.0 to AHK v1.1 advice]:
AHK v1 to AHK v2 conversion tips/changes summary - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 37&t=36787
note: the code is set up for a UK keyboard, but there are other variants you can uncomment (search for 'HotkeysLine')

Code: Select all

; http://ahkscript.org/germans/forums/viewtopic.php?t=6803
; Klavier Hero by Bentschi
; Modified version to support AHK v1.1 x64/x32 Unicode/ANSI and UK keyboard

#SingleInstance, force

Volume=100
Device=0 ;(0=Standard)
Instrument=1 ;Klavier
Channel=1
Oktav=1

KbdW = 400
KbdH = 80
DrawMode = 1 ;OpenGL

Instruments =
(Join|
1 Acoustic Grand Piano|
2 Bright Piano
3 Electric Grand Piano
4 Honky-tonk piano
5 Electric Piano 1
6 Electric Piano 2
7 Harpsichord
8 Clav
9 Celesta
10 Glockenspiel
11 Music Box
12 Vibraphone
13 Marimba
14 Xylophone
15 Tubular Bells
16 Dulcimer
17 Drawbar Organ
18 Percussive Organ
19 Rock Organ
20 Church Organ
21 Reed Organ
22 Accordian
23 Harmonica
24 Tango Accordian
25 Nylon String Guitar
26 Steel String Guitar
27 Jazz Guitar
28 Clean Electric Guitar
29 Muted Electric Guitar
30 Overdrive Guitar
31 Distortion Guitar
32 Guitar Harmonics
33 Acoustic Bass
34 Fingered Bass
35 Picked Bass
36 Fretless Bass
37 Slap Bass 1
38 Slap Bass 2
39 Synth Bass 1
40 Synth Bass 2
41 Violin
42 Viola
43 Cello
44 Contrabass
45 Tremolo Strings
46 Pizzicato Strings
47 Orchestral Harp
48 Timpani
49 String Ensemble 1
50 String Ensemble 2
51 Synth Strings 1
52 Synth Strings 2
53 Choir Ahh
54 Choir Oohh
55 Synth Voice
56 Orchestral Hit
57 Trumpet
58 Trombone
59 Tuba
60 Muted Trumpet
61 French Horn
62 Brass Section
63 Synth Brass 1
64 Synth Brass 2
65 Soprano Sax
66 Alto Sax
67 Tenor Sax
68 Baritone Sax
69 Oboe
70 English Horn
71 Bassoon
72 Clarinet
73 Piccolo
74 Flute
75 Recorder
76 Pan Flute
77 Blown Bottle
78 Shakuhachi
79 Whistle
80 Ocarina
81 Square Wav
82 Sawtooth Wav
83 Caliope
84 Chiff
85 Charang
86 Voice
87 Fifth's
88 Bass&Lead
89 New Age
90 Warm
91 Polysynth
92 Choir
93 Bowed
94 Metallic
95 Halo
96 Sweep
97 FX Rain
98 FX Soundtrack
99 FX Crystal
100 FX Atmosphere
101 FX Brightness
102 FX Goblins
103 FX Echo Drops
104 FX Star Theme
105 Sitar
106 Banjo
107 Shamisen
108 Koto
109 Kalimba
110 Bagpipe
111 Fiddle
112 Shanai
113 Tinkle Bell
114 Agogo
115 Steel Drums
116 Woodblock
117 Taiko Drum
118 Melodic Tom
119 Synth Drum
120 Reverse Cymbal
121 Guitar Fret Noise
122 Breath Noise
123 Seashore
124 Bird Tweet
125 Telephone Ring
126 Helicopter
127 Applause
128 Gunshot
)
WM_KEYDOWN = 0x100
WM_KEYUP = 0x101
WM_LBUTTONDOWN = 0x201
WM_LBUTTONUP = 0x202

/* ;German keyboard
HotkeysLine1 = 226, 65, 89, 83, 88, 68, 67, 86, 71, 66, 72, 78, 77, 75, 188, 76, 190, 192, 189
; <aysxdcvgbhnmk,l.ö-
HotkeysLine2 = 81, 50, 87, 51, 69, 82, 53, 84, 54, 90, 55, 85, 73, 57, 79, 48, 80
; q2w3er5t6z7ui9o0pü´+
*/

; US keyboard
HotkeysLine1 = 226,65,90,83,88,68,67,86,71,66,72,78,77,75,188,76,190,190,191
; \azsxdcvgbhnmk,l.;/
HotkeysLine2 = 81,50,87,51,69,82,53,84,54,89,55,85,73,57,79,48,80,53,187,186
; q2w3er5t6y7ui9o0p[=]

; UK keyboard
HotkeysLine1 = 220,65,90,83,88,68,67,86,71,66,72,78,77,75,188,76,190,186,191
; \azsxdcvgbhnmk,l.;/
HotkeysLine2 = 81,50,87,51,69,82,53,84,54,89,55,85,73,57,79,48,80,219,187,221
; q2w3er5t6y7ui9o0p[=]

Hotkeys := HotkeysLine1 ", " HotkeysLine2
Loop, parse, HotKeys, `,, % A_Space A_Tab
{
  Key%A_Loopfield% := A_Index
  MKey%A_Index% := A_Loopfield
  NumKeys := A_Index
}

WinMM_Lib := DllCall("LoadLibrary", Str, "Winmm.dll", Ptr)
NumDevs := DllCall("winmm.dll\midiOutGetNumDevs", UInt)
loop, % NumDevs
{
  VarSetCapacity(DevCaps, 52, 0)
  DllCall("winmm.dll\midiOutGetDevCapsA", UPtr, A_Index-1, Ptr, &DevCaps, UInt, 52, UInt)
  Name =
  Loop, 32
  {
    Name .= Chr(NumGet(DevCaps, A_Index+7, "UChar"))
  }
  VarSetCapacity(DevCaps, 0)
  DevName%A_Index% := Name
  if A_Index = 1
    DevNames := Name
  else
    DevNames .= "|" Name
}
Gui, add, ddl, x-200 y-200 w0 h0 vFocusButton
Gui, add, text, x10 y10 cBlue, Instrument:
Gui, add, listbox, xp y+3 w150 h300 +Altsubmit gChooseInstr vList, % Instruments
Gui, add, text, x+10 y10 cBlue, Treiber:
Gui, add, ddl, xp y+3 w200 +Altsubmit vDev gChooseDev, % DevNames
GuiControl, Choose, Dev, % Device+1
Gui, add, text, xp y+15 cBlue, Velocity:
Gui, add, slider, xp y+3 w200 vVol gChooseVol +0x100 range0-127, % Volume
Gui, add, text, xp y+5 cBlue, Kanal:
Gui, add, ddl, xp y+3 w200 +Altsubmit vChannel gChooseChannel, Kanal 1||Kanal 2|Kanal 3|Kanal 4
Gui, add, text, xp y+15 cBlue, Virtuelles Klavier:
Gui, add, ddl, xp y+3 w200 +AltSubmit vDrawMode gChooseDrawMode, [Ausblenden]|OpenGL
Gui, add, text, xp y+15 cBlue, Oktav:
Gui, add, edit, xp y+3 w200
Gui, add, updown, range-2-4 vOktav gChooseOktav, % Oktav
GuiControl, Choose, DrawMode, % DrawMode+1
Gui +LastFound
hWnd := WinExist()
Gui, show,, Klavier Hero 2010
Gosub, InitMidi
OnExit, ExitSub
OnMessage(WM_KEYDOWN, "PlayTone", 10)
OnMessage(WM_KEYUP, "ReleaseTone", 10)
OnMessage(WM_LBUTTONDOWN, "MouseClick")
OnMessage(WM_LBUTTONUP, "MouseRelease")
Gosub, EnableDraw
return

ChooseDev:
GuiControlGet, Device,, Dev
Device -= 1
return

ChooseVol:
GuiControlGet, Volume,, Vol
return

ChooseChannel:
GuiControlGet, Channel
return

ChooseOktav:
GuiControlGet, Oktav
return

InitMidi:
if (Device > NumDevs)
  Device = 0
if (hMidiOut)
  Gosub, FreeMidi
midiOutShortMsg := DllCall("GetProcAddress", Ptr, WinMM_Lib, AStr, "midiOutShortMsg", Ptr)
VarSetCapacity(hMidiOutp, A_PtrSize, 0)
DllCall("winmm.dll\midiOutOpen", Ptr, &hMidiOutp, UInt, Device, UPtr, 0, UPtr, 0, UInt, 0, UInt)
hMidiOut := NumGet(hMidiOutp, 0, "Ptr")
VarSetCapacity(hMidiOutp, 0)
return

ChooseInstr:
GuiControlGet, Instrument,, List
Instrument -= 1
return

FreeMidi:
DllCall("winmm.dll\midiOutReset", Ptr, hMidiOut, UInt)
DllCall("winmm.dll\midiOutClose", Ptr, hMidiOut, UInt)
return

GuiClose:
ExitSub:
Gui, hide
GoSub, DisableDraw
GoSub, FreeMidi
DllCall("FreeLibrary", Ptr, WinMM_Lib)
ExitApp

PlayTone(wParam, lParam)
{
  Global
  Local cTone
  ;Tooltip, % wParam

  if (Key%wParam%) && (Key%wParam%down!=1)
  {
    cTone := (Key%wParam% + 52) + ((Oktav - 1) * 12)
    GuiControl, Focus, Focusbutton
    DllCall(midiOutShortMsg, Ptr, hMidiOut, UInt, (256 * Instrument) + Channel+191, UInt)
    DllCall(midiOutShortMsg, Ptr, hMidiOut, UInt, (65536 * Volume) + (256 * cTone) + Channel+143, UInt)
    KeyIndex := Key%wParam%
    Key%wParam%down=1
    KeyI%KeyIndex%down=1
  }
  return
}

ReleaseTone(wParam, lParam)
{
  Global
  Local cTone
  if (Key%wParam%down=1)
  {
    KeyIndex := Key%wParam%
    Key%wParam%down=0
    KeyI%KeyIndex%down=0
    cTone := (Key%wParam% + 52) + ((Oktav - 1) * 12)
    DllCall(midiOutShortMsg, Ptr, hMidiOut, UInt, (65536 * Volume) + (256 * cTone) + Channel+127, UInt)
  }
  return
}

MouseClick(wParam, lParam, msg, handle)
{
  Global
  if (DrawMode) && (handle=hWnd2)
  {
    MouseClick = 0
    MouseX := (lParam & 0xFFFF) / KbdW * 100
    MouseY := (lParam >> 16) / KbdH * 10
    CalcXPos := KeyWW - (KeyBW / 2)
    Index = 1
    Loop, % NumKeys
    {
      if Index in 2,4,6,9,11
      {
        if (MouseX < (CalcXPos + KeyBW)) && (MouseX > CalcXPos) && (MouseY < 10/4*2.5)
        {
          MouseClick := A_Index
          break
        }
        CalcXPos := CalcXPos + KeyWW
      }
      if Index in 6,11
        CalcXPos := CalcXPos + KeyWW
      Index++
      if Index > 12
        Index = 1
    }
    if !(MouseClick)
    {
      CalcXPos = 0
      Index = 1
      Loop, % NumKeys
      {
        if Index in 1,3,5,7,8,10,12
        {
          if (MouseX > CalcXPos) && (MouseX < (CalcXPos + KeyWW))
          {
            MouseClick := A_Index
            break
          }
          CalcXPos := CalcXPos + KeyWW
        }
        Index++
        if Index > 12
          Index = 1
      }
    }
    PlayTone(MKey%MouseClick%, 0)
  }
  return
}

MouseRelease(wParam, lParam, msg, handle)
{
  Global
  ReleaseTone(MKey%MouseClick%, 0)
  MouseClick = 0
  return
}

ChooseDrawMode:
GuiControlGet, DrawMode
DrawMode--

EnableDraw:
Gui, 2: +LastFound +Resize -MinimizeBox -MaximizeBox -dpiscale
hWnd2 := WinExist()
if (DrawModeInit)
  gosub, DisableDraw
if (DrawMode=1)
  goto, InitOpenGL
return

2GuiClose:
GuiControl, 1:Choose, DrawMode, 1
DisableDraw:
Gui, 2:hide
if (DrawModeInit=1)
{
  SetTimer, UpdateOpenGL, Off
  DllCall("opengl32.dll\wglMakeCurrent", Ptr, 0, Ptr, 0)
  DllCall("opengl32.dll\wglDeleteContext", Ptr, hRC)
  DllCall("ReleaseDC", Ptr, hWnd2, Ptr, hDC)
  DllCall("FreeLibrary", Ptr, hOpenGL)
  DllCall("FreeLibrary", Ptr, hGdi32)
}
DrawModeInit=0
return

2GuiSize:
KbdW := A_GuiWidth
KbdH := A_GuiHeight
return

InitOpenGL:
DrawModeInit=1
hOpenGL := DllCall("LoadLibrary", Str, "opengl32.dll", Ptr)
hGdi32  := DllCall("LoadLibrary", Str, "gdi32.dll", Ptr)
hDC := DllCall("GetDC", Ptr, hWnd2, Ptr)
VarSetCapacity(pfd, 40, 0)
NumPut(40, pfd, 0, "UShort")
NumPut(1, pfd, 2, "UShort")
NumPut((0x04 | 0x20 | 0x01), pfd, 4, "UInt")
NumPut(32, pfd, 9, "UChar")
NumPut(16, pfd, 23, "UChar")
NumPut(0, pfd, 8, "UChar")
NumPut(0, pfd, 26, "UChar")
PixelFormat := DllCall("ChoosePixelFormat", Ptr, hDC, Ptr, &pfd)
DllCall("SetPixelFormat", Ptr, hDC, Int, PixelFormat, Ptr, &pfd)
hRC := DllCall("opengl32.dll\wglCreateContext", Ptr, hDC, Ptr)
DllCall("opengl32.dll\wglMakeCurrent", Ptr, hDC, Ptr, hRC)
SwapBuffers := DllCall("GetProcAddress", Ptr, hGdi32, AStr, "SwapBuffers", Ptr)
glClear := DllCall("GetProcAddress", Ptr, hOpenGL, AStr, "glClear", Ptr)
glViewport := DllCall("GetProcAddress", Ptr, hOpenGL, AStr, "glViewport", Ptr)
glMatrixMode := DllCall("GetProcAddress", Ptr, hOpenGL, AStr, "glMatrixMode", Ptr)
glLoadIdentity := DllCall("GetProcAddress", Ptr, hOpenGL, AStr, "glLoadIdentity", Ptr)
glOrtho := DllCall("GetProcAddress", Ptr, hOpenGL, AStr, "glOrtho", Ptr)
glVertex2f := DllCall("GetProcAddress", Ptr, hOpenGL, AStr, "glVertex2f", Ptr)
glScalef := DllCall("GetProcAddress", Ptr, hOpenGL, AStr, "glScalef", Ptr)
glTranslatef := DllCall("GetProcAddress", Ptr, hOpenGL, AStr, "glTranslatef", Ptr)
glCallList := DllCall("GetProcAddress", Ptr, hOpenGL, AStr, "glCallList", Ptr)
glPushMatrix := DllCall("GetProcAddress", Ptr, hOpenGL, AStr, "glPushMatrix", Ptr)
glPopMatrix := DllCall("GetProcAddress", Ptr, hOpenGL, AStr, "glPopMatrix", Ptr)
glColor4f := DllCall("GetProcAddress", Ptr, hOpenGL, AStr, "glColor4f", Ptr)
glEnable := DllCall("GetProcAddress", Ptr, hOpenGL, AStr, "glEnable", Ptr)
glDisable := DllCall("GetProcAddress", Ptr, hOpenGL, AStr, "glDisable", Ptr)
GL_COLOR_BUFFER_BIT := 0x00004000
GL_MODELVIEW := 0x1700

GL_PROJECTION := 0x1701
GL_COMPILE := 0x1300
GL_TRIANGLES := 0x0004
GL_QUADS := 0x0007
GL_LINE_LOOP := 0x0002
GL_BLEND := 0x0BE2
GL_SRC_ALPHA := 0x0302

GL_ONE_MINUS_SRC_ALPHA := 0x0303
GL_LINE_SMOOTH := 0x0B20
DllCall("opengl32.dll\glBlendFunc", Int, GL_SRC_ALPHA, Int, GL_ONE_MINUS_SRC_ALPHA)

NumWKeys=0
Index = 1
Loop, % NumKeys
{
  if Index in 1,3,5,7,8,10,12
    NumWKeys++
  Index++
  if Index > 12
    Index = 1
}
KeyWW := 100/NumWKeys
KeyBW := KeyWW/4*2.5
KeyC := 5
List := DllCall("opengl32.dll\glGenLists", Int, 6, UInt)
DllCall("opengl32.dll\glNewList", UInt, List+0, Int, GL_COMPILE)
DllCall(glLoadIdentity)
DllCall("opengl32.dll\glColor4f", Float, 0, Float, 0, Float, 0, Float, 1)
DllCall("opengl32.dll\glBegin", Int, GL_LINE_LOOP)
DllCall(glVertex2f, Float, 0.001, Float, 0.001)
DllCall(glVertex2f, Float, 0.001, Float, 9.999)
DllCall(glVertex2f, Float, 99.999, Float, 9.999)
DllCall(glVertex2f, Float, 99.999, Float, 0.001)
DllCall("opengl32.dll\glEnd")
DllCall("opengl32.dll\glEndList")

DllCall("opengl32.dll\glNewList", UInt, List+1, Int, GL_COMPILE)
DllCall("opengl32.dll\glBegin", Int, GL_QUADS)
DllCall("opengl32.dll\glColor4f", Float, 0.5, Float, 0.5, Float, 0.5, Float, 1)
DllCall(glVertex2f, Float, 0, Float, 0)
DllCall(glVertex2f, Float, KeyWW, Float, 0)
DllCall("opengl32.dll\glColor4f", Float, 1, Float, 1, Float, 1, Float, 1)
DllCall(glVertex2f, Float, KeyWW, Float, 1)
DllCall(glVertex2f, Float, 0, Float, 1)
DllCall(glVertex2f, Float, 0, Float, 1)
DllCall(glVertex2f, Float, KeyWW, Float, 1)
DllCall(glVertex2f, Float, KeyWW, Float, 9.6)
DllCall(glVertex2f, Float, 0, Float, 9.6)
DllCall("opengl32.dll\glEnd")
DllCall("opengl32.dll\glColor4f", Float, 0, Float, 0, Float, 0, Float, 1)
DllCall("opengl32.dll\glBegin", Int, GL_LINE_LOOP)
DllCall(glVertex2f, Float, 0, Float, 0)
DllCall(glVertex2f, Float, KeyWW, Float, 0)
DllCall(glVertex2f, Float, KeyWW, Float, 9.6)
DllCall(glVertex2f, Float, 0, Float, 9.6)
DllCall("opengl32.dll\glEnd")
DllCall("opengl32.dll\glTranslatef", Float, KeyWW, Float, 0, Float, 0)
DllCall("opengl32.dll\glEndList")

DllCall("opengl32.dll\glNewList", UInt, List+2, Int, GL_COMPILE)
DllCall("opengl32.dll\glTranslatef", Float, KeyWW, Float, 0, Float, 0)
DllCall("opengl32.dll\glBegin", Int, GL_QUADS)
DllCall("opengl32.dll\glColor4f", Float, 0.15, Float, 0.15, Float, 0.15, Float, 1)
DllCall(glVertex2f, Float, -(KeyBW/2), Float, 0)
DllCall(glVertex2f, Float, KeyBW/2, Float, 0)
DllCall(glVertex2f, Float, KeyBW/2, Float, 10/4*2.5)
DllCall(glVertex2f, Float, -(KeyBW/2), Float, 10/4*2.5)
DllCall("opengl32.dll\glColor4f", Float, 0.2, Float, 0.2, Float, 0.2, Float, 1)
DllCall(glVertex2f, Float, -(KeyBW/4), Float, 0.5)
DllCall(glVertex2f, Float, KeyBW/4, Float, 0.5)
DllCall("opengl32.dll\glColor4f", Float, 0.5, Float, 0.5, Float, 0.5, Float, 1)
DllCall(glVertex2f, Float, KeyBW/4, Float, 10/4*2.0)
DllCall(glVertex2f, Float, -(KeyBW/4), Float, 10/4*2.0)
DllCall("opengl32.dll\glColor4f", Float, 0.2, Float, 0.2, Float, 0.2, Float, 1)
DllCall(glVertex2f, Float, -(KeyBW/4), Float, 0.5)
DllCall(glVertex2f, Float, KeyBW/4, Float, 0.5)
DllCall("opengl32.dll\glColor4f", Float, 0.5, Float, 0.5, Float, 0.5, Float, 1)
DllCall(glVertex2f, Float, KeyBW/2, Float, 0)
DllCall(glVertex2f, Float, -(KeyBW/2), Float, 0)
DllCall("opengl32.dll\glColor4f", Float, 0.3, Float, 0.3, Float, 0.3, Float, 1)
DllCall(glVertex2f, Float, -(KeyBW/4), Float, 10/4*2.0)
DllCall(glVertex2f, Float, KeyBW/4, Float, 10/4*2.0)
DllCall("opengl32.dll\glColor4f", Float, 0.2, Float, 0.2, Float, 0.2, Float, 1)
DllCall(glVertex2f, Float, KeyBW/2, Float, 10/4*2.5)
DllCall(glVertex2f, Float, -(KeyBW/2), Float, 10/4*2.5)
DllCall("opengl32.dll\glEnd")
DllCall("opengl32.dll\glEndList")

DllCall("opengl32.dll\glNewList", UInt, List+3, Int, GL_COMPILE)
DllCall("opengl32.dll\glBegin", Int, GL_QUADS)
DllCall("opengl32.dll\glColor4f", Float, 0.4, Float, 0.4, Float, 0.4, Float, 1)
DllCall(glVertex2f, Float, 0, Float, 0)
DllCall(glVertex2f, Float, KeyWW, Float, 0)
DllCall("opengl32.dll\glColor4f", Float, 0.9, Float, 0.9, Float, 0.9, Float, 1)
DllCall(glVertex2f, Float, KeyWW, Float, 1.5)
DllCall(glVertex2f, Float, 0, Float, 1.5)
DllCall(glVertex2f, Float, 0, Float, 1.5)
DllCall(glVertex2f, Float, KeyWW, Float, 1.5)
DllCall("opengl32.dll\glColor4f", Float, 0.7, Float, 0.7, Float, 0.7, Float, 1)
DllCall(glVertex2f, Float, KeyWW, Float, 9.6)
DllCall(glVertex2f, Float, 0, Float, 9.6)
DllCall(glVertex2f, Float, 0, Float, 9.6)
DllCall(glVertex2f, Float, KeyWW, Float, 9.6)
DllCall(glVertex2f, Float, KeyWW-0.4, Float, 9.7)
DllCall(glVertex2f, Float, 0.4, Float, 9.7)
DllCall("opengl32.dll\glEnd")
DllCall("opengl32.dll\glColor4f", Float, 0, Float, 0, Float, 0, Float, 1)
DllCall("opengl32.dll\glBegin", Int, GL_LINE_LOOP)
DllCall(glVertex2f, Float, 0, Float, 0)
DllCall(glVertex2f, Float, KeyWW, Float, 0)
DllCall(glVertex2f, Float, KeyWW, Float, 9.6)
DllCall(glVertex2f, Float, KeyWW-0.4, Float, 9.7)
DllCall(glVertex2f, Float, 0.4, Float, 9.7)
DllCall(glVertex2f, Float, 0, Float, 9.6)
DllCall("opengl32.dll\glEnd")
DllCall("opengl32.dll\glTranslatef", Float, KeyWW, Float, 0, Float, 0)
DllCall("opengl32.dll\glEndList")

DllCall("opengl32.dll\glNewList", UInt, List+4, Int, GL_COMPILE)
DllCall("opengl32.dll\glTranslatef", Float, KeyWW, Float, 0, Float, 0)
DllCall("opengl32.dll\glBegin", Int, GL_QUADS)
DllCall("opengl32.dll\glColor4f", Float, 0, Float, 0, Float, 0, Float, 1)
DllCall(glVertex2f, Float, -(KeyBW/2), Float, 0)
DllCall(glVertex2f, Float, KeyBW/2, Float, 0)
DllCall(glVertex2f, Float, KeyBW/2, Float, 10/4*2.5)
DllCall(glVertex2f, Float, -(KeyBW/2), Float, 10/4*2.5)
DllCall("opengl32.dll\glColor4f", Float, 0.1, Float, 0.1, Float, 0.1, Float, 1)
DllCall(glVertex2f, Float, -(KeyBW/4), Float, 0.5)
DllCall(glVertex2f, Float, KeyBW/4, Float, 0.5)
DllCall("opengl32.dll\glColor4f", Float, 0.25, Float, 0.25, Float, 0.25, Float, 1)
DllCall(glVertex2f, Float, KeyBW/4, Float, 10/4*2.0)
DllCall(glVertex2f, Float, -(KeyBW/4), Float, 10/4*2.0)
DllCall("opengl32.dll\glColor4f", Float, 0.1, Float, 0.1, Float, 0.1, Float, 1)
DllCall(glVertex2f, Float, -(KeyBW/4), Float, 0.5)
DllCall(glVertex2f, Float, KeyBW/4, Float, 0.5)
DllCall("opengl32.dll\glColor4f", Float, 0.25, Float, 0.25, Float, 0.25, Float, 1)
DllCall(glVertex2f, Float, KeyBW/2, Float, 0)
DllCall(glVertex2f, Float, -(KeyBW/2), Float, 0)
DllCall("opengl32.dll\glColor4f", Float, 0.15, Float, 0.15, Float, 0.15, Float, 1)
DllCall(glVertex2f, Float, -(KeyBW/4), Float, 10/4*2.0)
DllCall(glVertex2f, Float, KeyBW/4, Float, 10/4*2.0)
DllCall("opengl32.dll\glColor4f", Float, 0.1, Float, 0.1, Float, 0.1, Float, 1)
DllCall(glVertex2f, Float, KeyBW/2, Float, 10/4*2.5)
DllCall(glVertex2f, Float, -(KeyBW/2), Float, 10/4*2.5)
DllCall("opengl32.dll\glEnd")
DllCall("opengl32.dll\glEndList")

PointSize = 1
DllCall("opengl32.dll\glNewList", UInt, List+5, Int, GL_COMPILE)
DllCall("opengl32.dll\glEnable", Int, GL_BLEND)
DllCall("opengl32.dll\glBegin", Int, GL_TRIANGLES)
DllCall("opengl32.dll\glColor4f", Float, 1, Float, 0, Float, 0, Float, 1)
DllCall(glVertex2f, Float, 0, Float, 0)
DllCall("opengl32.dll\glColor4f", Float, 1, Float, 0, Float, 0, Float, 0)
DllCall(glVertex2f, Float, 0, Float, PointSize)
DllCall(glVertex2f, Float, sin(10.0531)*PointSize, Float, -(cos(10.0531)*PointSize))
DllCall("opengl32.dll\glEnd")
DllCall("opengl32.dll\glDisable", Int, GL_BLEND)
DllCall("opengl32.dll\glEndList")

DllCall("opengl32.dll\glNewList", UInt, List+6, Int, GL_COMPILE)
DllCall("opengl32.dll\glTranslatef", Float, 0, Float, 8, Float, 0)
DllCall(glScalef, Float, 1.2, Float, 1, Float, 1)
Loop, 10
{
  DllCall(glCallList, UInt, List+5)
  DllCall("opengl32.dll\glRotatef", Float, 36, Float, 0, Float, 0, Float, 1)
}
DllCall("opengl32.dll\glEndList")
FontOut := DllCall("opengl32.dll\glGenLists", Int, Asc("Z")-Asc("A")+1, UInt)
FontIn := DllCall("opengl32.dll\glGenLists", Int, Asc("Z")-Asc("A")+1, UInt)
hFont := DllCall("CreateFont", Int, -1, Int, 0, Int, 0, Int, 0, Int, 800, UInt, 0, UInt, 0, UInt, 0, UInt, 0, UInt, 4, UInt, 0, UInt, 4, UInt, 0, Ptr, 0, Ptr)
DllCall("SelectObject", Ptr, hDC, Ptr, hFont, Ptr)
VarSetCapacity(gmf, (Asc("Z")-Asc("A")+1)*24, 0)
DllCall("opengl32.dll\wglUseFontOutlinesA", Ptr, hDC, UInt, Asc("A"), UInt, Asc("Z")-Asc("A")+1, UInt, FontOut, Float, 0, Float, 0.2, Int, 0, Ptr, &gmf)
DllCall("opengl32.dll\wglUseFontOutlinesA", Ptr, hDC, UInt, Asc("A"), UInt, Asc("Z")-Asc("A")+1, UInt, FontIn, Float, 0, Float, 0.2, Int, 1, Ptr, 0)
Gui, 2:show, w%KbdW% h%KbdH%, Virtuelles Klavier
SetTimer, UpdateOpenGL, 50
return

UpdateOpenGL:
Critical
DllCall(glClear, UInt, GL_COLOR_BUFFER_BIT)
DllCall(glViewport, Int, 0, Int, 0, Int, KbdW, Int, KbdH)
DllCall(glMatrixMode, Int, GL_PROJECTION)
DllCall(glLoadIdentity)
DllCall(glOrtho, Double, 0, Double, 100, Double, 10, Double, 0, Double, -1, Double, 1)
DllCall(glMatrixMode, Int, GL_MODELVIEW)
DllCall(glLoadIdentity)
Index = 1
cOktav = 1
Loop, % NumKeys
{
  if Index in 1,3,5,7,8,10,12
  {
    DllCall(glCallList, UInt, ((KeyI%A_Index%down) ? List+3 : List+1))
    if (MKey%A_Index% >= Asc("A")) && (MKey%A_Index% <= Asc("Z"))
    {
      DllCall(glPushMatrix)
      DllCall(glTranslatef, Float, -(KeyWW*0.8), Float, 9, Float, 0)
      DllCall(glScalef, Float, 3, Float, -3, Float, 1)
      DllCall(glPushMatrix)
      if (Index = 8) && (cOktav = Oktav)
        DllCall(glColor4f, Float, 1, Float, 0.5, Float, 0.5, Float, 0.5)
      else
        DllCall(glColor4f, Float, 0.7, Float, 0.7, Float, 0.7, Float, 0.5)
      DllCall(glEnable, Int, GL_BLEND)
      DllCall(glEnable, Int, GL_LINE_SMOOTH)
      DllCall(glCallList, UInt, FontOut+MKey%A_Index%-Asc("A"))
      DllCall(glDisable, Int, GL_LINE_SMOOTH)
      DllCall(glDisable, Int, GL_BLEND)
      DllCall(glPopMatrix)
      if (Index = 8) && (cOktav = Oktav)
        DllCall(glColor4f, Float, 1, Float, 0.5, Float, 0.5, Float, 1)
      else
        DllCall(glColor4f, Float, 0.7, Float, 0.7, Float, 0.7, Float, 1)
      DllCall(glCallList, UInt, FontIn+MKey%A_Index%-Asc("A"))
      DllCall(glPopMatrix)
    }
  }
  Index++
  if Index > 12
  {
    Index = 1
    cOktav--
  }
}
DllCall(glLoadIdentity)
Index = 1
Loop, % NumKeys
{
  if Index in 2,4,6,9,11
    DllCall(glCallList, UInt, ((KeyI%A_Index%down) ? List+4 : List+2))
  if Index in 6,11
    DllCall(glTranslatef, Float, KeyWW, Float, 0, Float, 0)
  Index++
  if Index > 12
    Index = 1
}
;DllCall(glLoadIdentity)
;DllCall("opengl32.dll\glTranslatef", Float, KeyWW*4.5, Float, 0, Float, 0)
;DllCall(glCallList, UInt, List+6)
DllCall(SwapBuffers, Ptr, hDC)
return
Last edited by jeeswg on 18 Apr 2018, 04:00, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: GUI: piano keyboard

18 Apr 2018, 02:00

Thanks but I'm not interested at all in AHK v2. Syntax remains as it was with only minor changes/improvements. It might even be compatible with AHK 1.0 and Win9x (although that would require more work), but unfortunately can't test that now.
I haven't checked all OpenGL calls either, they're just too many and I wasn't feeling well last night. Maybe these days I'll do it.
Labels were also changed to English since not everybody knows German.
Only tested in AHK 1.1 Unicode x86 under XP. If anyone tests this under x64, please provide feedback.

You have a bug in your version, one of the VKs is duplicated in HotkeysLine1 which makes one note unplayable.

There is one drawback I noticed: when system is under more or less heavy load, timing becomes inaccurate, script lags. This may not happen on modern multiprocessor computers but I don't own such machine to test on.

Code: Select all

; http://ahkscript.org/germans/forums/viewtopic.php?t=6803
; Klavier Hero by Bentschi
; Modified version to support AHK v1.1 x32 Unicode and US keyboard
; Modified again by Drugwash to use scan codes and proper data types

#NoEnv
#SingleInstance force
#WinActivateForce
SetTitleMatchMode, 2
SetBatchLines, -1
SetWinDelay, -1
SetControlDelay, -1
SetKeyDelay, -1, -1
SetMouseDelay, -1
ListLines, Off
SetFormat, Integer, D
SetWorkingDir, %A_ScriptDir%
DetectHiddenWindows, On

AW := A_IsUnicode ? "W" : "A", A_CharSize := A_IsUnicode ? 2 : 1 ; these can be found in some newer scripts of mine, in updates.ahk
Volume:=100
Device:=0 ;(0=Standard)
Instrument:=1 ;Klavier
Channel:=1
Oktav:=1

KbdW := 400
KbdH := 80
DrawMode := 1 ;OpenGL

Instruments =
(Join|
1 Acoustic Grand Piano|
2 Bright Piano
3 Electric Grand Piano
4 Honky-tonk piano
5 Electric Piano 1
6 Electric Piano 2
7 Harpsichord
8 Clav
9 Celesta
10 Glockenspiel
11 Music Box
12 Vibraphone
13 Marimba
14 Xylophone
15 Tubular Bells
16 Dulcimer
17 Drawbar Organ
18 Percussive Organ
19 Rock Organ
20 Church Organ
21 Reed Organ
22 Accordian
23 Harmonica
24 Tango Accordian
25 Nylon String Guitar
26 Steel String Guitar
27 Jazz Guitar
28 Clean Electric Guitar
29 Muted Electric Guitar
30 Overdrive Guitar
31 Distortion Guitar
32 Guitar Harmonics
33 Acoustic Bass
34 Fingered Bass
35 Picked Bass
36 Fretless Bass
37 Slap Bass 1
38 Slap Bass 2
39 Synth Bass 1
40 Synth Bass 2
41 Violin
42 Viola
43 Cello
44 Contrabass
45 Tremolo Strings
46 Pizzicato Strings
47 Orchestral Harp
48 Timpani
49 String Ensemble 1
50 String Ensemble 2
51 Synth Strings 1
52 Synth Strings 2
53 Choir Ahh
54 Choir Oohh
55 Synth Voice
56 Orchestral Hit
57 Trumpet
58 Trombone
59 Tuba
60 Muted Trumpet
61 French Horn
62 Brass Section
63 Synth Brass 1
64 Synth Brass 2
65 Soprano Sax
66 Alto Sax
67 Tenor Sax
68 Baritone Sax
69 Oboe
70 English Horn
71 Bassoon
72 Clarinet
73 Piccolo
74 Flute
75 Recorder
76 Pan Flute
77 Blown Bottle
78 Shakuhachi
79 Whistle
80 Ocarina
81 Square Wav
82 Sawtooth Wav
83 Caliope
84 Chiff
85 Charang
86 Voice
87 Fifth's
88 Bass&Lead
89 New Age
90 Warm
91 Polysynth
92 Choir
93 Bowed
94 Metallic
95 Halo
96 Sweep
97 FX Rain
98 FX Soundtrack
99 FX Crystal
100 FX Atmosphere
101 FX Brightness
102 FX Goblins
103 FX Echo Drops
104 FX Star Theme
105 Sitar
106 Banjo
107 Shamisen
108 Koto
109 Kalimba
110 Bagpipe
111 Fiddle
112 Shanai
113 Tinkle Bell
114 Agogo
115 Steel Drums
116 Woodblock
117 Taiko Drum
118 Melodic Tom
119 Synth Drum
120 Reverse Cymbal
121 Guitar Fret Noise
122 Breath Noise
123 Seashore
124 Bird Tweet
125 Telephone Ring
126 Helicopter
127 Applause
128 Gunshot
)
WM_KEYDOWN := 0x100
WM_KEYUP := 0x101
WM_LBUTTONDOWN := 0x201
WM_LBUTTONUP := 0x202

charL := Asc("A"), charH := Asc("Z"), charR := charH - charL + 1
HotkeysLine1 := "56,1E,2C,1F,2D,20,2E,2F,22,30,23,31,32,25,33,26,34,27,35"
HotkeysLine2 := "10,03,11,04,12,13,06,14,07,15,08,16,17,0A,18,0B,19,1A,0D,1B"

Hotkeys := HotkeysLine1 "," HotkeysLine2
Loop, Parse, Hotkeys, CSV
	{
	sc := "0x" A_Loopfield, sc+=0
	Key%sc% := A_Index
	MKey%A_Index% := sc
	NumKeys := A_Index
	}

WinMM_Lib := DllCall("kernel32\LoadLibrary" AW, "Str", "Winmm.dll", "Ptr")
NumDevs := DllCall("Winmm\midiOutGetNumDevs"), sz := 20+32*A_CharSize
Loop, % NumDevs
	{
	VarSetCapacity(DevCaps, sz, 0)
	DllCall("Winmm\midiOutGetDevCaps" AW, "UInt", A_Index-1, "Ptr", &DevCaps, "UInt", sz)
	Name := StrGet(&DevCaps+8)
	DevName%A_Index% := Name
	if A_Index = 1
	DevNames := Name
	else DevNames .= "|" Name
	}
VarSetCapacity(DevCaps, 0)
Gui, add, ddl, x-200 y-200 w0 h0 vFocusButton
Gui, add, text, x10 y10 cBlue, Instrument:
Gui, add, listbox, xp y+3 w150 h300 +Altsubmit gChooseInstr vList, % Instruments
Gui, add, text, x+10 y10 cBlue, Device:
Gui, add, ddl, xp y+3 w200 +Altsubmit vDev gChooseDev, % DevNames
GuiControl, Choose, Dev, % Device+1
Gui, add, text, xp y+15 cBlue, Volume:
Gui, add, slider, xp y+3 w200 vVol gChooseVol +0x100 range0-127, % Volume
Gui, add, text, xp y+5 cBlue, Channel:
Gui, add, ddl, xp y+3 w200 +Altsubmit vChannel gChooseChannel
	, Channel 1||Channel 2|Channel 3|Channel 4
Gui, add, text, xp y+15 cBlue, Virtual keyboard:
Gui, add, ddl, xp y+3 w200 +AltSubmit vDrawMode gChooseDrawMode, [External]|OpenGL
Gui, add, text, xp y+15 cBlue, Octave:
Gui, add, edit, xp y+3 w200
Gui, add, updown, range-2-4 vOktav gChooseOktav, % Oktav
GuiControl, Choose, DrawMode, % DrawMode+1
Gui +LastFound
hWnd := WinExist()
Gui, Show,, Klavier Hero 2010
Gosub, InitMidi
OnExit, ExitSub
OnMessage(WM_KEYDOWN, "PlayTone", 10)
OnMessage(WM_KEYUP, "ReleaseTone", 10)
OnMessage(WM_LBUTTONDOWN, "MouseClick")
OnMessage(WM_LBUTTONUP, "MouseRelease")
Gosub, EnableDraw
return

ChooseDev:
GuiControlGet, Device,, Dev
Device -= 1
return

ChooseVol:
GuiControlGet, Volume,, Vol
return

ChooseChannel:
GuiControlGet, Channel
return

ChooseOktav:
GuiControlGet, Oktav
return

InitMidi:
if (Device > NumDevs)
  Device := 0
if (hMidiOut)
  Gosub, FreeMidi
midiOutShortMsg := DllCall("GetProcAddress", "Ptr", WinMM_Lib, "AStr", "midiOutShortMsg")
VarSetCapacity(hMidiOut, A_PtrSize, 0)
DllCall("Winmm\midiOutOpen", "PtrP", hMidiOut, "UInt", Device, "Ptr", 0, "Ptr", 0, "UInt", 0)
return

ChooseInstr:
GuiControlGet, Instrument,, List
Instrument -= 1
return

FreeMidi:
DllCall("Winmm\midiOutReset", "Ptr", hMidiOut)
DllCall("Winmm\midiOutClose", "Ptr", hMidiOut)
return

GuiClose:
ExitSub:
Gui, Hide
GoSub, DisableDraw
GoSub, FreeMidi
DllCall("FreeLibrary", "Ptr", WinMM_Lib)
ExitApp

PlayTone(wParam, lParam)
{
Global
Local cTone, sc
sc := (lParam>>16)&0xFF
if (Key%sc%) && (Key%sc%down!=1)
	{
	cTone := (Key%sc% + 52) + ((Oktav - 1) * 12)
	GuiControl, Focus, Focusbutton
	DllCall(midiOutShortMsg, "Ptr", hMidiOut, "UInt", (256 * Instrument) + Channel+191)
	DllCall(midiOutShortMsg, "Ptr", hMidiOut, "UInt", (65536 * Volume) + (256 * cTone) + Channel+143)
	KeyIndex := Key%sc%
	Key%sc%down := KeyI%KeyIndex%down := 1
	}
return
}

ReleaseTone(wParam, lParam)
{
Global
Local cTone, sc
sc := (lParam>>16)&0xFF
if (Key%sc%down=1)
	{
	KeyIndex := Key%sc%
	Key%sc%down := KeyI%KeyIndex%down := 0
	cTone := (Key%sc% + 52) + ((Oktav - 1) * 12)
	DllCall(midiOutShortMsg, "Ptr", hMidiOut, "UInt", (65536 * Volume) + (256 * cTone) + Channel+127)
	}
return
}

MouseClick(wParam, lParam, msg, handle)
{
  Global
  if (DrawMode) && (handle=hWnd2)
  {
    MouseClick = 0
    MouseX := (lParam & 0xFFFF) / KbdW * 100
    MouseY := (lParam >> 16) / KbdH * 10
    CalcXPos := KeyWW - (KeyBW / 2)
    Index := 1
    Loop, % NumKeys
    {
      if Index in 2,4,6,9,11
      {
        if (MouseX < (CalcXPos + KeyBW)) && (MouseX > CalcXPos) && (MouseY < 10/4*2.5)
        {
          MouseClick := A_Index
          break
        }
        CalcXPos := CalcXPos + KeyWW
      }
      if Index in 6,11
        CalcXPos := CalcXPos + KeyWW
      Index++
      if Index > 12
        Index := 1
    }
    if !(MouseClick)
    {
      CalcXPos := 0
      Index := 1
      Loop, % NumKeys
      {
        if Index in 1,3,5,7,8,10,12
        {
          if (MouseX > CalcXPos) && (MouseX < (CalcXPos + KeyWW))
          {
            MouseClick := A_Index
            break
          }
          CalcXPos := CalcXPos + KeyWW
        }
        Index++
        if Index > 12
          Index := 1
      }
    }
    PlayTone(0, MKey%MouseClick%<<16)
  }
  return
}

MouseRelease(wParam, lParam, msg, handle)
{
  Global
  ReleaseTone(0, MKey%MouseClick%<<16)
  MouseClick := 0
  return
}

ChooseDrawMode:
GuiControlGet, DrawMode
DrawMode--

EnableDraw:
Gui, 2: +LastFound +Resize -MinimizeBox -MaximizeBox -DPIscale
hWnd2 := WinExist()
if (DrawModeInit)
  gosub, DisableDraw
if (DrawMode=1)
  goto, InitOpenGL
return

2GuiClose:
GuiControl, 1:Choose, DrawMode, 1
DisableDraw:
Gui, 2:Hide
if (DrawModeInit=1)
	{
	SetTimer, UpdateOpenGL, Off
	DllCall("opengl32\wglMakeCurrent", UInt, 0, UInt, 0)
	DllCall("opengl32\wglDeleteContext", "Ptr", hRC)
	DllCall("SelectObject", "Ptr", hDC, "Ptr", hOFont)
	DllCall("ReleaseDC", "Ptr", hWnd2, "Ptr", hDC)
	DllCall("FreeLibrary", "Ptr", hOpenGL)
	DllCall("FreeLibrary", "Ptr", hGdi32)
	DllCall("DeleteObject", "Ptr", hFont)
	}
DrawModeInit:=0
return

2GuiSize:
KbdW := A_GuiWidth
KbdH := A_GuiHeight
return


InitOpenGL:
DrawModeInit:=1
hOpenGL := DllCall("LoadLibrary" AW, "Str", "opengl32.dll")
hGdi32  := DllCall("LoadLibrary" AW, "Str", "gdi32.dll")
hDC := DllCall("GetDC", "Ptr", hWnd2, "Ptr")
VarSetCapacity(pfd, 40, 0)
NumPut(40, pfd, 0, "UShort")
NumPut(1, pfd, 2, "UShort")
NumPut((0x04 | 0x20 | 0x01), pfd, 4, "UInt")
NumPut(32, pfd, 9, "UChar")
NumPut(16, pfd, 23, "UChar")
NumPut(0, pfd, 8, "UChar")
NumPut(0, pfd, 26, "UChar")
PixelFormat := DllCall("gdi32\ChoosePixelFormat", "Ptr", hDC, "Ptr", &pfd)
DllCall("gdi32\SetPixelFormat", "Ptr", hDC, "UInt", PixelFormat, "Ptr", &pfd)
hRC := DllCall("opengl32\wglCreateContext", "Ptr", hDC, "Ptr")
DllCall("opengl32\wglMakeCurrent", "Ptr", hDC, "Ptr", hRC)
SwapBuffers := DllCall("GetProcAddress", "Ptr", hGdi32, "AStr", "SwapBuffers")
glClear := DllCall("GetProcAddress", "Ptr", hOpenGL, "AStr", "glClear")
glViewport := DllCall("GetProcAddress", "Ptr", hOpenGL, "AStr", "glViewport")
glMatrixMode := DllCall("GetProcAddress", "Ptr", hOpenGL, "AStr", "glMatrixMode")
glLoadIdentity := DllCall("GetProcAddress", "Ptr", hOpenGL, "AStr", "glLoadIdentity")
glOrtho := DllCall("GetProcAddress", "Ptr", hOpenGL, "AStr", "glOrtho")
glVertex2f := DllCall("GetProcAddress", "Ptr", hOpenGL, "AStr", "glVertex2f")
glScalef := DllCall("GetProcAddress", "Ptr", hOpenGL, "AStr", "glScalef")
glTranslatef := DllCall("GetProcAddress", "Ptr", hOpenGL, "AStr", "glTranslatef")
glCallList := DllCall("GetProcAddress", "Ptr", hOpenGL, "AStr", "glCallList")
glPushMatrix := DllCall("GetProcAddress", "Ptr", hOpenGL, "AStr", "glPushMatrix")
glPopMatrix := DllCall("GetProcAddress", "Ptr", hOpenGL, "AStr", "glPopMatrix")
glColor4f := DllCall("GetProcAddress", "Ptr", hOpenGL, "AStr", "glColor4f")
glEnable := DllCall("GetProcAddress", "Ptr", hOpenGL, "AStr", "glEnable")
glDisable := DllCall("GetProcAddress", "Ptr", hOpenGL, "AStr", "glDisable")
GL_COLOR_BUFFER_BIT := 0x00004000
GL_MODELVIEW := 0x1700

GL_PROJECTION := 0x1701
GL_COMPILE := 0x1300
GL_TRIANGLES := 0x0004
GL_QUADS := 0x0007
GL_LINE_LOOP := 0x0002
GL_BLEND := 0x0BE2
GL_SRC_ALPHA := 0x0302

GL_ONE_MINUS_SRC_ALPHA := 0x0303
GL_LINE_SMOOTH := 0x0B20
DllCall("opengl32\glBlendFunc", "UInt", GL_SRC_ALPHA, "UInt", GL_ONE_MINUS_SRC_ALPHA)

NumWKeys:=0
Index := 1
Loop, % NumKeys
{
  if Index in 1,3,5,7,8,10,12
    NumWKeys++
  Index++
  if Index > 12
    Index := 1
}
KeyWW := 100/NumWKeys
KeyBW := KeyWW/4*2.5
KeyC := 5
List := DllCall("opengl32\glGenLists", "UInt", 6)
DllCall("opengl32\glNewList", "UInt", List+0, "UInt", GL_COMPILE)
DllCall(glLoadIdentity)
DllCall("opengl32\glColor4f", float, 0, float, 0, float, 0, float, 1)
DllCall("opengl32\glBegin", uint, GL_LINE_LOOP)
DllCall(glVertex2f, float, 0.001, float, 0.001)
DllCall(glVertex2f, float, 0.001, float, 9.999)
DllCall(glVertex2f, float, 99.999, float, 9.999)
DllCall(glVertex2f, float, 99.999, float, 0.001)
DllCall("opengl32.dll\glEnd")
DllCall("opengl32.dll\glEndList")

DllCall("opengl32.dll\glNewList", uint, List+1, uint, GL_COMPILE)
DllCall("opengl32.dll\glBegin", uint, GL_QUADS)
DllCall("opengl32.dll\glColor4f", float, 0.5, float, 0.5, float, 0.5, float, 1)
DllCall(glVertex2f, float, 0, float, 0)
DllCall(glVertex2f, float, KeyWW, float, 0)
DllCall("opengl32.dll\glColor4f", float, 1, float, 1, float, 1, float, 1)
DllCall(glVertex2f, float, KeyWW, float, 1)
DllCall(glVertex2f, float, 0, float, 1)
DllCall(glVertex2f, float, 0, float, 1)
DllCall(glVertex2f, float, KeyWW, float, 1)
DllCall(glVertex2f, float, KeyWW, float, 9.6)
DllCall(glVertex2f, float, 0, float, 9.6)
DllCall("opengl32.dll\glEnd")
DllCall("opengl32.dll\glColor4f", float, 0, float, 0, float, 0, float, 1)
DllCall("opengl32.dll\glBegin", uint, GL_LINE_LOOP)
DllCall(glVertex2f, float, 0, float, 0)
DllCall(glVertex2f, float, KeyWW, float, 0)
DllCall(glVertex2f, float, KeyWW, float, 9.6)
DllCall(glVertex2f, float, 0, float, 9.6)
DllCall("opengl32.dll\glEnd")
DllCall("opengl32.dll\glTranslatef", Float, KeyWW, Float, 0, Float, 0)
DllCall("opengl32.dll\glEndList")

DllCall("opengl32.dll\glNewList", uint, List+2, uint, GL_COMPILE)
DllCall("opengl32.dll\glTranslatef", Float, KeyWW, Float, 0, Float, 0)
DllCall("opengl32.dll\glBegin", uint, GL_QUADS)
DllCall("opengl32.dll\glColor4f", float, 0.15, float, 0.15, float, 0.15, float, 1)
DllCall(glVertex2f, float, -(KeyBW/2), float, 0)
DllCall(glVertex2f, float, KeyBW/2, float, 0)
DllCall(glVertex2f, float, KeyBW/2, float, 10/4*2.5)
DllCall(glVertex2f, float, -(KeyBW/2), float, 10/4*2.5)
DllCall("opengl32.dll\glColor4f", float, 0.2, float, 0.2, float, 0.2, float, 1)
DllCall(glVertex2f, float, -(KeyBW/4), float, 0.5)
DllCall(glVertex2f, float, KeyBW/4, float, 0.5)
DllCall("opengl32.dll\glColor4f", float, 0.5, float, 0.5, float, 0.5, float, 1)
DllCall(glVertex2f, float, KeyBW/4, float, 10/4*2.0)
DllCall(glVertex2f, float, -(KeyBW/4), float, 10/4*2.0)
DllCall("opengl32.dll\glColor4f", float, 0.2, float, 0.2, float, 0.2, float, 1)
DllCall(glVertex2f, float, -(KeyBW/4), float, 0.5)
DllCall(glVertex2f, float, KeyBW/4, float, 0.5)
DllCall("opengl32.dll\glColor4f", float, 0.5, float, 0.5, float, 0.5, float, 1)
DllCall(glVertex2f, float, KeyBW/2, float, 0)
DllCall(glVertex2f, float, -(KeyBW/2), float, 0)
DllCall("opengl32.dll\glColor4f", float, 0.3, float, 0.3, float, 0.3, float, 1)
DllCall(glVertex2f, float, -(KeyBW/4), float, 10/4*2.0)
DllCall(glVertex2f, float, KeyBW/4, float, 10/4*2.0)
DllCall("opengl32.dll\glColor4f", float, 0.2, float, 0.2, float, 0.2, float, 1)
DllCall(glVertex2f, float, KeyBW/2, float, 10/4*2.5)
DllCall(glVertex2f, float, -(KeyBW/2), float, 10/4*2.5)
DllCall("opengl32.dll\glEnd")
DllCall("opengl32.dll\glEndList")

DllCall("opengl32.dll\glNewList", uint, List+3, uint, GL_COMPILE)
DllCall("opengl32.dll\glBegin", uint, GL_QUADS)
DllCall("opengl32.dll\glColor4f", float, 0.4, float, 0.4, float, 0.4, float, 1)
DllCall(glVertex2f, float, 0, float, 0)
DllCall(glVertex2f, float, KeyWW, float, 0)
DllCall("opengl32.dll\glColor4f", float, 0.9, float, 0.9, float, 0.9, float, 1)
DllCall(glVertex2f, float, KeyWW, float, 1.5)
DllCall(glVertex2f, float, 0, float, 1.5)
DllCall(glVertex2f, float, 0, float, 1.5)
DllCall(glVertex2f, float, KeyWW, float, 1.5)
DllCall("opengl32.dll\glColor4f", float, 0.7, float, 0.7, float, 0.7, float, 1)
DllCall(glVertex2f, float, KeyWW, float, 9.6)
DllCall(glVertex2f, float, 0, float, 9.6)
DllCall(glVertex2f, float, 0, float, 9.6)
DllCall(glVertex2f, float, KeyWW, float, 9.6)
DllCall(glVertex2f, float, KeyWW-0.4, float, 9.7)
DllCall(glVertex2f, float, 0.4, float, 9.7)
DllCall("opengl32.dll\glEnd")
DllCall("opengl32.dll\glColor4f", float, 0, float, 0, float, 0, float, 1)
DllCall("opengl32.dll\glBegin", uint, GL_LINE_LOOP)
DllCall(glVertex2f, float, 0, float, 0)
DllCall(glVertex2f, float, KeyWW, float, 0)
DllCall(glVertex2f, float, KeyWW, float, 9.6)
DllCall(glVertex2f, float, KeyWW-0.4, float, 9.7)
DllCall(glVertex2f, float, 0.4, float, 9.7)
DllCall(glVertex2f, float, 0, float, 9.6)
DllCall("opengl32.dll\glEnd")
DllCall("opengl32.dll\glTranslatef", Float, KeyWW, Float, 0, Float, 0)
DllCall("opengl32.dll\glEndList")

DllCall("opengl32.dll\glNewList", uint, List+4, uint, GL_COMPILE)
DllCall("opengl32.dll\glTranslatef", Float, KeyWW, Float, 0, Float, 0)
DllCall("opengl32.dll\glBegin", uint, GL_QUADS)
DllCall("opengl32.dll\glColor4f", float, 0, float, 0, float, 0, float, 1)
DllCall(glVertex2f, float, -(KeyBW/2), float, 0)
DllCall(glVertex2f, float, KeyBW/2, float, 0)
DllCall(glVertex2f, float, KeyBW/2, float, 10/4*2.5)
DllCall(glVertex2f, float, -(KeyBW/2), float, 10/4*2.5)
DllCall("opengl32.dll\glColor4f", float, 0.1, float, 0.1, float, 0.1, float, 1)
DllCall(glVertex2f, float, -(KeyBW/4), float, 0.5)
DllCall(glVertex2f, float, KeyBW/4, float, 0.5)
DllCall("opengl32.dll\glColor4f", float, 0.25, float, 0.25, float, 0.25, float, 1)
DllCall(glVertex2f, float, KeyBW/4, float, 10/4*2.0)
DllCall(glVertex2f, float, -(KeyBW/4), float, 10/4*2.0)
DllCall("opengl32.dll\glColor4f", float, 0.1, float, 0.1, float, 0.1, float, 1)
DllCall(glVertex2f, float, -(KeyBW/4), float, 0.5)
DllCall(glVertex2f, float, KeyBW/4, float, 0.5)
DllCall("opengl32.dll\glColor4f", float, 0.25, float, 0.25, float, 0.25, float, 1)
DllCall(glVertex2f, float, KeyBW/2, float, 0)
DllCall(glVertex2f, float, -(KeyBW/2), float, 0)
DllCall("opengl32.dll\glColor4f", float, 0.15, float, 0.15, float, 0.15, float, 1)
DllCall(glVertex2f, float, -(KeyBW/4), float, 10/4*2.0)
DllCall(glVertex2f, float, KeyBW/4, float, 10/4*2.0)
DllCall("opengl32.dll\glColor4f", float, 0.1, float, 0.1, float, 0.1, float, 1)
DllCall(glVertex2f, float, KeyBW/2, float, 10/4*2.5)
DllCall(glVertex2f, float, -(KeyBW/2), float, 10/4*2.5)
DllCall("opengl32\glEnd")
DllCall("opengl32\glEndList")

PointSize := 1
DllCall("opengl32\glNewList", uint, List+5, uint, GL_COMPILE)
DllCall("opengl32\glEnable", uint, GL_BLEND)
DllCall("opengl32\glBegin", uint, GL_TRIANGLES)
DllCall("opengl32\glColor4f", float, 1, float, 0, float, 0, float, 1)
DllCall(glVertex2f, float, 0, float, 0)
DllCall("opengl32\glColor4f", float, 1, float, 0, float, 0, float, 0)
DllCall(glVertex2f, float, 0, float, PointSize)
DllCall(glVertex2f, float, sin(10.0531)*PointSize, float, -(cos(10.0531)*PointSize))
DllCall("opengl32\glEnd")
DllCall("opengl32\glDisable", uint, GL_BLEND)
DllCall("opengl32\glEndList")

DllCall("opengl32\glNewList", uint, List+6, uint, GL_COMPILE)
DllCall("opengl32\glTranslatef", Float, 0, Float, 8, Float, 0)
DllCall(glScalef, float, 1.2, float, 1, float, 1)
Loop, 10
	{
	DllCall(glCallList, "UInt", List+5)
	DllCall("opengl32\glRotatef", "Float", 36, "Float", 0, "Float", 0, "Float", 1)
	}
DllCall("opengl32\glEndList")
FontOut := DllCall("opengl32\glGenLists", "UInt", charR)
FontIn := DllCall("opengl32\glGenLists", "UInt", charR)
hFont := DllCall("CreateFont"
	, "Int", -1
	, "Int", 0
	, "Int", 0
	, "Int", 0
	, "Int", 800
	, "UInt", 0
	, "UInt", 0
	, "UInt", 0
	, "UInt", 0
	, "UInt", 4
	, "UInt", 0
	, "UInt", 4
	, "UInt", 0
	, "Ptr", 0
	, "Ptr")
hOFont := DllCall("SelectObject", "Ptr", hDC, "Ptr", hFont, "Ptr")
VarSetCapacity(gmf, charR*24, 0)
DllCall("opengl32\wglUseFontOutlines" AW
	, "Ptr", hDC
	, "UInt", charL
	, "UInt", charR
	, "UInt", FontOut
	, "Float", 0
	, "Float", 0.2
	, "Int", 0
	, "Ptr", &gmf)
DllCall("opengl32\wglUseFontOutlines" AW
	, "Ptr", hDC
	, "UInt", charL
	, "UInt", charR
	, "UInt", FontIn
	, "Float", 0
	, "Float", 0.2
	, "Int", 1
	, "Ptr", 0)
Gui, 2:Show, w%KbdW% h%KbdH%, Virtual keyboard
SetTimer, UpdateOpenGL, 50
return

UpdateOpenGL:
Critical
DllCall(glClear, "UInt", GL_COLOR_BUFFER_BIT)
DllCall(glViewport, "Int", 0, "Int", 0, "Int", KbdW, "Int", KbdH)
DllCall(glMatrixMode, "UInt", GL_PROJECTION)
DllCall(glLoadIdentity)
DllCall(glOrtho, "Double", 0, "Double", 100, "Double", 10, "Double", 0, "Double", -1, "Double", 1)
DllCall(glMatrixMode, "UInt", GL_MODELVIEW)
DllCall(glLoadIdentity)
Index := 1
cOktav := 1
Loop, % NumKeys
	{
	if Index in 1,3,5,7,8,10,12
		{
		DllCall(glCallList, "UInt", ((KeyI%A_Index%down) ? List+3 : List+1))
		VK := GetKeyVK(Format("sc{:x}", MKey%A_Index%))
		if VK between %charL% and %charH%
			{
			DllCall(glPushMatrix)
			DllCall(glTranslatef, "Float", -(KeyWW*0.8), "Float", 9, "Float", 0)
			DllCall(glScalef, "Float", 3, "Float", -3, "Float",  1)
			DllCall(glPushMatrix)
			if (Index = 8) && (cOktav = Oktav)
				DllCall(glColor4f, "Float", 1, "Float", 0.5, "Float", 0.5, "Float", 0.5)
			else DllCall(glColor4f, "Float", 0.7, "Float", 0.7, "Float", 0.7, "Float", 0.5)
			DllCall(glEnable, "UInt", GL_BLEND)
			DllCall(glEnable, "UInt", GL_LINE_SMOOTH)
			DllCall(glCallList, "UInt", FontOut+VK-charL)
			DllCall(glDisable, "UInt", GL_LINE_SMOOTH)
			DllCall(glDisable, "UInt", GL_BLEND)
			DllCall(glPopMatrix)
			if (Index = 8) && (cOktav = Oktav)
				DllCall(glColor4f, "Float", 1, "Float", 0.5, "Float", 0.5, "Float", 1)
			else DllCall(glColor4f, "Float", 0.7, "Float", 0.7, "Float", 0.7, "Float", 1)
			DllCall(glCallList, "UInt", FontIn+VK-charL)
			DllCall(glPopMatrix)
			}
		}
	Index++
	if Index > 12
		{
		Index := 1
		cOktav--
		}
	}
DllCall(glLoadIdentity)
Index := 1
Loop, % NumKeys
	{
	if Index in 2,4,6,9,11
		DllCall(glCallList, "UInt", ((KeyI%A_Index%down) ? List+4 : List+2))
	if Index in 6,11
		DllCall(glTranslatef, "Float", KeyWW, "Float", 0, "Float", 0)
	Index++
	if Index > 12
		Index := 1
	}
;DllCall(glLoadIdentity)
;DllCall("opengl32\glTranslatef", Float, KeyWW*4.5, Float, 0, Float, 0)
;DllCall(glCallList, UInt, List+6)
DllCall(SwapBuffers, "Ptr", hDC)
return

Part of my AHK work can be found here.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI: piano keyboard

18 Apr 2018, 02:58

- Ah, the name of my link was a bit misleading, it has general conversion advice for all versions, not just for AHK v2. All of the code I've posted on this thread is for AHK v1.1.
- SpeedMaster changed the script to run on a some keyboard or other, I've used that code. My code from earlier, should make it possible to set up the keys for whatever keyboard you have.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: GUI: piano keyboard

18 Apr 2018, 03:14

Indeed the link name is misleading. And I'm too lazy to actually check it out. :)
Usage of scancodes should eliminate these layout problems, they can even be switched on the fly. The only problem I see is for 101 keyboards that would miss the leftmost note (below A).
There still are minor things to fix regarding some OpenGL calls, I'm working on that at the moment.
Have you tested it yet, at least in x86?
Part of my AHK work can be found here.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI: piano keyboard

18 Apr 2018, 03:24

- I have some code to automate correcting the OpenGL calls, I just to need make an adjustment to support Str/AStr/WStr, not just Ptr, then I'll update my code above.
- My script above is working on AHK v1.1 x64 and x32, Unicode and ANSI.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: GUI: piano keyboard

18 Apr 2018, 03:37

I like to do corections manually (what a blasphemy to say that in an automation tool's forum board! :lol: ), if only to understand better how the script works. ;)

Have you tested my version in x64? I don't have such machine here.
Yours is still using a few ANSI calls regardless of the AHK encoding. I put them all on an automated switch (that AW variable that should've been in AHK by default long ago together with A_CharSize).

[EDIT]
Please check line 387, both parameters should be pointers:
DllCall("opengl32.dll\wglMakeCurrent", Ptr, 0, Ptr, 0) First is HDC, secoond is HGLRC.
Line 417, parameter is also pointer:
hRC := DllCall("opengl32.dll\wglCreateContext", Ptr, hDC)
Same as line 387 above, in line 418:
DllCall("opengl32.dll\wglMakeCurrent", Ptr, hDC, Ptr, hRC)
Line 612 and 613 need a couple of pointers each and maybe use the AW approach:

Code: Select all

DllCall("opengl32.dll\wglUseFontOutlinesA", Ptr, hDC, UInt, Asc("A"), UInt, Asc("Z")-Asc("A")+1, UInt, FontOut, Float, 0, Float, 0.2, Int, 0, Ptr, &gmf)
DllCall("opengl32.dll\wglUseFontOutlinesA", Ptr, hDC, UInt, Asc("A"), UInt, Asc("Z")-Asc("A")+1, UInt, FontIn, Float, 0, Float, 0.2, Int, 1, Ptr, 0)
That's about it, at a quick look.
Part of my AHK work can be found here.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI: piano keyboard

18 Apr 2018, 04:09

- @Drugwash: I tested your script, and unfortunately it was not working on AHK v1.1 x64. [EDIT:] The script worked apart from the GUI keyboard, the subwindow opened but the keyboard didn't show.
- I basically prepared a list of dll functions and parameter types, and automatically converted the DllCall lines (and checked using WinMerge). I also went over NumGet/NumPut/VarSetCapacity (and DllCall) lines manually.
- You are so right re. the variables, even now there should be two variables that give W or A, and 2 or 1, and it's the sort of thing I would like backported to 'AHK v1.0.50'.
- Btw it's not always necessary to convert an 'A' function to a 'W' function, I just left lines 612 and 613 as 'A'.
- All of the corrections that you mentioned were handled correctly by my converter. The updated script is available above. Cheers.
Last edited by jeeswg on 18 Apr 2018, 14:50, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: GUI: piano keyboard

18 Apr 2018, 06:59

How strange. What exactly do you mean by "it was not working"?
- was the MIDI device detected properly (name appears in the top list)?
- does keyboard appear with characters drawn on them?
- does it play any sound at all, on any key or mouse click?
- are you using an USB keyboard? Maybe scancodes are different.
Ah, just noticed I didn't have the correct return data types for the GL procedures. Maybe that was it.

A few years ago I had started updating AHK 1.0.48.05 but got too greedy and messed up, then got sidetracked by other things and lost interest. It had AW, A_CharSize, A_PtrSize and other BIVs implemented in AHK 1.1.

The wglUseFontOutlines() API builds the characters that are to be displayed on keys. Currently it only works with capital A to Z latin characters, moreso when only the ANSI version of it is used, which is a limitation because there are so many different keyboards in this world and not all of them have native latin characters on the caps, or at least not all of them are in the A-Z range. I intend to perform an on-the-fly conversion from scancode to actual (Unicode) characters and add an option for the user to select their actual layout as it physically appears on the keyboard, so the correct characters would be displayed in the virtual keyboard. Well, at least it's a nice idea. :)

Please try this one, hopefully it'll work in x64:
(fixed thanks to jeeswg)

Code: Select all

; http://ahkscript.org/germans/forums/viewtopic.php?t=6803
; Klavier Hero by Bentschi
; Modified version to support AHK v1.1 x32 Unicode and US keyboard
; Modified again by Drugwash to use scan codes and proper data types [v1.1]

#NoEnv
#SingleInstance force
#WinActivateForce
SetTitleMatchMode, 2
SetBatchLines, -1
SetWinDelay, -1
SetControlDelay, -1
SetKeyDelay, -1, -1
SetMouseDelay, -1
ListLines, Off
SetFormat, Integer, D
SetWorkingDir, %A_ScriptDir%
DetectHiddenWindows, On
AW := A_IsUnicode ? "W" : "A", A_CharSize := A_IsUnicode ? 2 : 1

Vol := 85			; [%] Initial volume
Device := 0		; 0=Default
Instrument := 1	; [1-128] Default instrument
Channel := 1		; [1-4] Default channel
Oktav := 1			; [-2-4] Default octave

KbdW := 400		; [px] Initial keyboard width
KbdH := 80		; [px] Initial keyboard height
DrawMode := 1	; [0-1] Initial drawing mode (1=OpenGL)

Instruments =
(Join|
1 Acoustic Grand Piano
2 Bright Piano
3 Electric Grand Piano
4 Honky-tonk piano
5 Electric Piano 1
6 Electric Piano 2
7 Harpsichord
8 Clav
9 Celesta
10 Glockenspiel
11 Music Box
12 Vibraphone
13 Marimba
14 Xylophone
15 Tubular Bells
16 Dulcimer
17 Drawbar Organ
18 Percussive Organ
19 Rock Organ
20 Church Organ
21 Reed Organ
22 Accordian
23 Harmonica
24 Tango Accordian
25 Nylon String Guitar
26 Steel String Guitar
27 Jazz Guitar
28 Clean Electric Guitar
29 Muted Electric Guitar
30 Overdrive Guitar
31 Distortion Guitar
32 Guitar Harmonics
33 Acoustic Bass
34 Fingered Bass
35 Picked Bass
36 Fretless Bass
37 Slap Bass 1
38 Slap Bass 2
39 Synth Bass 1
40 Synth Bass 2
41 Violin
42 Viola
43 Cello
44 Contrabass
45 Tremolo Strings
46 Pizzicato Strings
47 Orchestral Harp
48 Timpani
49 String Ensemble 1
50 String Ensemble 2
51 Synth Strings 1
52 Synth Strings 2
53 Choir Ahh
54 Choir Oohh
55 Synth Voice
56 Orchestral Hit
57 Trumpet
58 Trombone
59 Tuba
60 Muted Trumpet
61 French Horn
62 Brass Section
63 Synth Brass 1
64 Synth Brass 2
65 Soprano Sax
66 Alto Sax
67 Tenor Sax
68 Baritone Sax
69 Oboe
70 English Horn
71 Bassoon
72 Clarinet
73 Piccolo
74 Flute
75 Recorder
76 Pan Flute
77 Blown Bottle
78 Shakuhachi
79 Whistle
80 Ocarina
81 Square Wav
82 Sawtooth Wav
83 Caliope
84 Chiff
85 Charang
86 Voice
87 Fifth's
88 Bass&Lead
89 New Age
90 Warm
91 Polysynth
92 Choir
93 Bowed
94 Metallic
95 Halo
96 Sweep
97 FX Rain
98 FX Soundtrack
99 FX Crystal
100 FX Atmosphere
101 FX Brightness
102 FX Goblins
103 FX Echo Drops
104 FX Star Theme
105 Sitar
106 Banjo
107 Shamisen
108 Koto
109 Kalimba
110 Bagpipe
111 Fiddle
112 Shanai
113 Tinkle Bell
114 Agogo
115 Steel Drums
116 Woodblock
117 Taiko Drum
118 Melodic Tom
119 Synth Drum
120 Reverse Cymbal
121 Guitar Fret Noise
122 Breath Noise
123 Seashore
124 Bird Tweet
125 Telephone Ring
126 Helicopter
127 Applause
128 Gunshot
)
WM_KEYDOWN := 0x100, WM_KEYUP := 0x101
WM_LBUTTONDOWN := 0x201, WM_LBUTTONUP := 0x202

charL := Asc("A"), charH := Asc("Z"), charR := charH - charL + 1
HotkeysLine1 := "56,1E,2C,1F,2D,20,2E,2F,22,30,23,31,32,25,33,26,34,27,35"
HotkeysLine2 := "10,03,11,04,12,13,06,14,07,15,08,16,17,0A,18,0B,19,1A,0D,1B"

Hotkeys := HotkeysLine1 "," HotkeysLine2
Loop, Parse, Hotkeys, CSV
	{
	sc := "0x" A_Loopfield, sc+=0
	Key%sc% := A_Index
	MKey%A_Index% := sc
	NumKeys := A_Index
	}

hWinMM := DllCall("kernel32\LoadLibrary" AW, "Str", "Winmm.dll", "Ptr")
NumDevs := DllCall("Winmm\midiOutGetNumDevs"), sz := 20+32*A_CharSize
Loop, % NumDevs
	{
	VarSetCapacity(DevCaps, sz, 0)
	DllCall("Winmm\midiOutGetDevCaps" AW, "UInt", A_Index-1, "Ptr", &DevCaps, "UInt", sz)
	Name := StrGet(&DevCaps+8)
	DevName%A_Index% := Name
	DevNames .= Name "|"
	}
StringTrimRight, DevNames, DevNames, 1
VarSetCapacity(DevCaps, 0), VarSetCapacity(Name, 0)
Volume := Round(Vol*127/100)

Gui, Add, DDL, x-200 y-200 w0 h0 vFocusButton
Gui, Add, Text, x10 y10 cBlue, Instrument:
Gui, Add, ListBox, xp y+3 w150 h300 +AltSubmit gChooseInstr vList, % Instruments
GuiControl, Choose, List, % Instrument
Gui, Add, Text, x+10 y10 cBlue, Device:
Gui, Add, DDL, xp y+3 w200 +AltSubmit vDev gChooseDev, % DevNames
GuiControl, Choose, Dev, % Device+1
Gui, Add, Text, xp y+15 cBlue vVolLabel, Volume: %Vol% `%%A_Space%%A_Space%
Gui, Add, Slider, xp y+3 w200 vVol gChooseVol +0x100 Range0-100, % Vol
Gui, Add, Text, xp y+5 cBlue, Channel:
Gui, Add, DDL, xp y+3 w200 +Altsubmit vChannel gChooseChannel
	, Channel 1||Channel 2|Channel 3|Channel 4
Gui, Add, Text, xp y+15 cBlue, Virtual keyboard:
Gui, Add, DDL, xp y+3 w200 +AltSubmit vDrawMode gChooseDrawMode, [Hidden]|OpenGL
Gui, Add, Text, xp y+15 cBlue, Octave:
Gui, Add, Edit, xp y+3 w200
Gui, Add, UpDown, Range-2-4 vOktav gChooseOktav, % Oktav
GuiControl, Choose, DrawMode, % DrawMode+1
Gui +LastFound
hWnd := WinExist()
Gui, Show,, Klavier Hero 2010

GoSub, InitMidi
OnExit, ExitSub
OnMessage(WM_KEYDOWN, "PlayTone", 10)
OnMessage(WM_KEYUP, "ReleaseTone", 10)
OnMessage(WM_LBUTTONDOWN, "MouseClick")
OnMessage(WM_LBUTTONUP, "MouseRelease")
GoSub, EnableDraw
Return

ChooseDev:
GuiControlGet, Device,, Dev
Device--
Return

ChooseVol:
GuiControlGet, Vol,, Vol
Volume := Round(Vol*127/100)
GuiControl,, VolLabel, Volume: %Vol% `%
Return

ChooseChannel:
GuiControlGet, Channel
Return

ChooseOktav:
GuiControlGet, Oktav
Return

InitMidi:
If (Device > NumDevs)
  Device := 0
If (hMidiOut)
  GoSub, FreeMidi
midiOutShortMsg := DllCall("kernel32\GetProcAddress", "Ptr", hWinMM, "AStr", "midiOutShortMsg", "Ptr")
VarSetCapacity(hMidiOut, A_PtrSize, 0)
DllCall("Winmm\midiOutOpen", "PtrP", hMidiOut, "UInt", Device, "Ptr", 0, "Ptr", 0, "UInt", 0)
Return

ChooseInstr:
GuiControlGet, Instrument,, List
Instrument--
Return

FreeMidi:
DllCall("Winmm\midiOutReset", "Ptr", hMidiOut)
DllCall("Winmm\midiOutClose", "Ptr", hMidiOut)
Return

GuiClose:
ExitSub:
Gui, Hide
GoSub, DisableDraw
GoSub, FreeMidi
DllCall("FreeLibrary", "Ptr", hWinMM)
ExitApp

PlayTone(wParam, lParam)
{
Global
Local cTone, sc
sc := (lParam>>16)&0xFF
If (Key%sc% && !Key%sc%down)
	{
	cTone := (Key%sc% + 52) + ((Oktav - 1) * 12)
	GuiControl, Focus, Focusbutton
	DllCall(midiOutShortMsg, "Ptr", hMidiOut, "UInt", (Instrument<<8) + Channel+191)
	DllCall(midiOutShortMsg, "Ptr", hMidiOut, "UInt", (Volume<<16) + (cTone<<8) + Channel+143)
	KeyIndex := Key%sc%
	Key%sc%down := KeyI%KeyIndex%down := 1
	}
Return
}

ReleaseTone(wParam, lParam)
{
Global
Local cTone, sc
sc := (lParam>>16)&0xFF
If Key%sc%down
	{
	KeyIndex := Key%sc%
	Key%sc%down := KeyI%KeyIndex%down := 0
	cTone := (Key%sc% + 52) + ((Oktav - 1) * 12)
	DllCall(midiOutShortMsg, "Ptr", hMidiOut, "UInt", (Volume<<16) + (cTone<<8) + Channel+127)
	}
Return
}

MouseClick(wParam, lParam, msg, handle)
{
Global
If (DrawMode && handle=hWnd2)
	{
	MouseClick := 0
	MouseX := (lParam & 0xFFFF) / KbdW * 100
	MouseY := (lParam >> 16) / KbdH * 10
	CalcXPos := KeyWW - (KeyBW / 2)
	Index := 1
	Loop, % NumKeys
		{
		If Index in 2,4,6,9,11
			{
			If (MouseX < (CalcXPos + KeyBW)) && (MouseX > CalcXPos) && (MouseY < 10/4*2.5)
				{
				MouseClick := A_Index
				Break
				}
			CalcXPos := CalcXPos + KeyWW
			}
		If Index in 6,11
			CalcXPos := CalcXPos + KeyWW
		Index++
		If Index > 12
			Index := 1
		}
	If !MouseClick
		{
		CalcXPos := 0
		Index := 1
		Loop, % NumKeys
			{
			If Index in 1,3,5,7,8,10,12
				{
				If (MouseX > CalcXPos) && (MouseX < (CalcXPos + KeyWW))
					{
					MouseClick := A_Index
					Break
					}
				CalcXPos := CalcXPos + KeyWW
				}
			Index++
			If Index > 12
				Index := 1
			}
		}
	PlayTone(0, MKey%MouseClick%<<16)
	}
Return
}

MouseRelease(wParam, lParam, msg, handle)
{
Global
ReleaseTone(0, MKey%MouseClick%<<16)
MouseClick := 0
Return
}

ChooseDrawMode:
GuiControlGet, DrawMode
DrawMode--

EnableDraw:
Gui, 2: +LastFound +Resize -MinimizeBox -MaximizeBox -DPIscale
hWnd2 := WinExist()
If DrawModeInit
  GoSub, DisableDraw
If DrawMode=1
  GoTo, InitOpenGL
Return

2GuiClose:
GuiControl, 1:Choose, DrawMode, 1
DisableDraw:
Gui, 2:Hide
If DrawModeInit
	{
	SetTimer, UpdateOpenGL, Off
	DllCall("opengl32\wglMakeCurrent", "Ptr", 0, "Ptr", 0)
	DllCall("opengl32\wglDeleteContext", "Ptr", hRC)
	DllCall("gdi32\SelectObject", "Ptr", hDC, "Ptr", hOFont)
	DllCall("user32\ReleaseDC", "Ptr", hWnd2, "Ptr", hDC)
	DllCall("gdi32\DeleteObject", "Ptr", hFont)
	DllCall("kernel32\FreeLibrary", "Ptr", hOpenGL)
	DllCall("kernel32\FreeLibrary", "Ptr", hGdi32)
	}
DrawModeInit := 0
Return

2GuiSize:
KbdW := A_GuiWidth, KbdH := A_GuiHeight
Return

InitOpenGL:
DrawModeInit := 1
hOpenGL := DllCall("kernel32\LoadLibrary" AW, "Str", "opengl32.dll", "Ptr")
hGdi32  := DllCall("kernel32\LoadLibrary" AW, "Str", "gdi32.dll", "Ptr")
hDC := DllCall("user32\GetDC", "Ptr", hWnd2, "Ptr")
VarSetCapacity(pfd, 40, 0)	; PIXELFORMATDESCRIPTOR struct
NumPut(40, pfd, 0, "UShort")	; nSize
NumPut(1, pfd, 2, "UShort")		; nVersion
NumPut(0x25, pfd, 4, "UInt")	; PFD_SUPPORT_OPENGL/DRAW_TO_WINDOW/DOUBLEBUFFER
NumPut(0, pfd, 8, "UChar")		; iPixelType PFD_TYPE_RGBA
NumPut(32, pfd, 9, "UChar")		; cColorBits
NumPut(16, pfd, 23, "UChar")	; cDepthBits
NumPut(0, pfd, 26, "UChar")		; iLayerType
PixelFormat := DllCall("gdi32\ChoosePixelFormat", "Ptr", hDC, "Ptr", &pfd)
DllCall("gdi32\SetPixelFormat", "Ptr", hDC, "UInt", PixelFormat, "Ptr", &pfd)
hRC := DllCall("opengl32\wglCreateContext", "Ptr", hDC, "Ptr")
DllCall("opengl32\wglMakeCurrent", "Ptr", hDC, "Ptr", hRC)
SwapBuffers := DllCall("kernel32\GetProcAddress", "Ptr", hGdi32, "AStr", "SwapBuffers", "Ptr")
glClear := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glClear", "Ptr")
glViewport := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glViewport", "Ptr")
glMatrixMode := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glMatrixMode", "Ptr")
glLoadIdentity := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glLoadIdentity", "Ptr")
glOrtho := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glOrtho", "Ptr")
glColor4f := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glColor4f", "Ptr")
glRotatef := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glRotatef", "Ptr")
glScalef := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glScalef", "Ptr")
glTranslatef := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glTranslatef", "Ptr")
glVertex2f := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glVertex2f", "Ptr")
glPushMatrix := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glPushMatrix", "Ptr")
glPopMatrix := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glPopMatrix", "Ptr")
glEnable := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glEnable", "Ptr")
glDisable := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glDisable", "Ptr")
glBegin := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glBegin", "Ptr")
glEnd := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glEnd", "Ptr")
glGenLists := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glGenLists", "Ptr")
glNewList := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glNewList", "Ptr")
glCallList := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glCallList", "Ptr")
glEndList := DllCall("kernel32\GetProcAddress", "Ptr", hOpenGL, "AStr", "glEndList", "Ptr")

GL_COLOR_BUFFER_BIT := 0x00004000
GL_MODELVIEW := 0x1700
GL_PROJECTION := 0x1701
GL_COMPILE := 0x1300
GL_TRIANGLES := 0x0004
GL_QUADS := 0x0007
GL_LINE_LOOP := 0x0002
GL_BLEND := 0x0BE2
GL_SRC_ALPHA := 0x0302
GL_ONE_MINUS_SRC_ALPHA := 0x0303
GL_LINE_SMOOTH := 0x0B20

DllCall("opengl32\glBlendFunc", "UInt", GL_SRC_ALPHA, "UInt", GL_ONE_MINUS_SRC_ALPHA)

NumWKeys := 0, Index := 1
Loop, % NumKeys
	{
	If Index in 1,3,5,7,8,10,12
		NumWKeys++
	Index++
	If Index > 12
		Index := 1
	}
KeyWW := 100/NumWKeys, KeyBW := KeyWW/4*2.5, KeyC := 5
KeyBW2 := KeyBW/2, KeyBW4 := KeyBW/4
List := DllCall(glGenLists, "UInt", 6)
DllCall(glNewList, "UInt", List+0, "UInt", GL_COMPILE)
DllCall(glLoadIdentity)
DllCall(glColor4f, "Float", 0, "Float", 0, "Float", 0, "Float", 1)
DllCall(glBegin, "UInt", GL_LINE_LOOP)
DllCall(glVertex2f, "Float", 0.001, "Float", 0.001)
DllCall(glVertex2f, "Float", 0.001, "Float", 9.999)
DllCall(glVertex2f, "Float", 99.999, "Float", 9.999)
DllCall(glVertex2f, "Float", 99.999, "Float", 0.001)
DllCall(glEnd)
DllCall(glEndList)

DllCall(glNewList, "UInt", List+1, "UInt", GL_COMPILE)
DllCall(glBegin, "UInt", GL_QUADS)
DllCall(glColor4f, "Float", 0.5, "Float", 0.5, "Float", 0.5, "Float", 1)
DllCall(glVertex2f, "Float", 0, "Float", 0)
DllCall(glVertex2f, "Float", KeyWW, "Float", 0)
DllCall(glColor4f, "Float", 1, "Float", 1, "Float", 1, "Float", 1)
DllCall(glVertex2f, "Float", KeyWW, "Float", 1)
DllCall(glVertex2f, "Float", 0, "Float", 1)
DllCall(glVertex2f, "Float", 0, "Float", 1)
DllCall(glVertex2f, "Float", KeyWW, "Float", 1)
DllCall(glVertex2f, "Float", KeyWW, "Float", 9.6)
DllCall(glVertex2f, "Float", 0, "Float", 9.6)
DllCall(glEnd)
DllCall(glColor4f, "Float", 0, "Float", 0, "Float", 0, "Float", 1)
DllCall(glBegin, "UInt", GL_LINE_LOOP)
DllCall(glVertex2f, "Float", 0, "Float", 0)
DllCall(glVertex2f, "Float", KeyWW, "Float", 0)
DllCall(glVertex2f, "Float", KeyWW, "Float", 9.6)
DllCall(glVertex2f, "Float", 0, "Float", 9.6)
DllCall(glEnd)
DllCall(glTranslatef, "Float", KeyWW, "Float", 0, "Float", 0)
DllCall(glEndList)

DllCall(glNewList, "UInt", List+2, "UInt", GL_COMPILE)
DllCall(glTranslatef, "Float", KeyWW, "Float", 0, "Float", 0)
DllCall(glBegin, "UInt", GL_QUADS)
DllCall(glColor4f, "Float", 0.15, "Float", 0.15, "Float", 0.15, "Float", 1)
DllCall(glVertex2f, "Float", -KeyBW2, "Float", 0)
DllCall(glVertex2f, "Float", KeyBW2, "Float", 0)
DllCall(glVertex2f, "Float", KeyBW2, "Float", 10/4*2.5)
DllCall(glVertex2f, "Float", -KeyBW2, "Float", 10/4*2.5)
DllCall(glColor4f, "Float", 0.2, "Float", 0.2, "Float", 0.2, "Float", 1)
DllCall(glVertex2f, "Float", -KeyBW4, "Float", 0.5)
DllCall(glVertex2f, "Float", KeyBW4, "Float", 0.5)
DllCall(glColor4f, "Float", 0.5, "Float", 0.5, "Float", 0.5, "Float", 1)
DllCall(glVertex2f, "Float", KeyBW4, "Float", 10/4*2.0)
DllCall(glVertex2f, "Float", -KeyBW4, "Float", 10/4*2.0)
DllCall(glColor4f, "Float", 0.2, "Float", 0.2, "Float", 0.2, "Float", 1)
DllCall(glVertex2f, "Float", -KeyBW4, "Float", 0.5)
DllCall(glVertex2f, "Float", KeyBW4, "Float", 0.5)
DllCall(glColor4f, "Float", 0.5, "Float", 0.5, "Float", 0.5, "Float", 1)
DllCall(glVertex2f, "Float", KeyBW2, "Float", 0)
DllCall(glVertex2f, "Float", -KeyBW2, "Float", 0)
DllCall(glColor4f, "Float", 0.3, "Float", 0.3, "Float", 0.3, "Float", 1)
DllCall(glVertex2f, "Float", -KeyBW4, "Float", 10/4*2.0)
DllCall(glVertex2f, "Float", KeyBW4, "Float", 10/4*2.0)
DllCall(glColor4f, "Float", 0.2, "Float", 0.2, "Float", 0.2, "Float", 1)
DllCall(glVertex2f, "Float", KeyBW2, "Float", 10/4*2.5)
DllCall(glVertex2f, "Float", -KeyBW2, "Float", 10/4*2.5)
DllCall(glEnd)
DllCall(glEndList)

DllCall(glNewList, "UInt", List+3, "UInt", GL_COMPILE)
DllCall(glBegin, "UInt", GL_QUADS)
DllCall(glColor4f, "Float", 0.4, "Float", 0.4, "Float", 0.4, "Float", 1)
DllCall(glVertex2f, "Float", 0, "Float", 0)
DllCall(glVertex2f, "Float", KeyWW, "Float", 0)
DllCall(glColor4f, "Float", 0.9, "Float", 0.9, "Float", 0.9, "Float", 1)
DllCall(glVertex2f, "Float", KeyWW, "Float", 1.5)
DllCall(glVertex2f, "Float", 0, "Float", 1.5)
DllCall(glVertex2f, "Float", 0, "Float", 1.5)
DllCall(glVertex2f, "Float", KeyWW, "Float", 1.5)
DllCall(glColor4f, "Float", 0.7, "Float", 0.7, "Float", 0.7, "Float", 1)
DllCall(glVertex2f, "Float", KeyWW, "Float", 9.6)
DllCall(glVertex2f, "Float", 0, "Float", 9.6)
DllCall(glVertex2f, "Float", 0, "Float", 9.6)
DllCall(glVertex2f, "Float", KeyWW, "Float", 9.6)
DllCall(glVertex2f, "Float", KeyWW-0.4, "Float", 9.7)
DllCall(glVertex2f, "Float", 0.4, "Float", 9.7)
DllCall(glEnd)
DllCall(glColor4f, "Float", 0, "Float", 0, "Float", 0, "Float", 1)
DllCall(glBegin, "UInt", GL_LINE_LOOP)
DllCall(glVertex2f, "Float", 0, "Float", 0)
DllCall(glVertex2f, "Float", KeyWW, "Float", 0)
DllCall(glVertex2f, "Float", KeyWW, "Float", 9.6)
DllCall(glVertex2f, "Float", KeyWW-0.4, "Float", 9.7)
DllCall(glVertex2f, "Float", 0.4, "Float", 9.7)
DllCall(glVertex2f, "Float", 0, "Float", 9.6)
DllCall(glEnd)
DllCall(glTranslatef, "Float", KeyWW, "Float", 0, "Float", 0)
DllCall(glEndList)

DllCall(glNewList, "UInt", List+4, "UInt", GL_COMPILE)
DllCall(glTranslatef, "Float", KeyWW, "Float", 0, "Float", 0)
DllCall(glBegin, "UInt", GL_QUADS)
DllCall(glColor4f, "Float", 0, "Float", 0, "Float", 0, "Float", 1)
DllCall(glVertex2f, "Float", -KeyBW2, "Float", 0)
DllCall(glVertex2f, "Float", KeyBW2, "Float", 0)
DllCall(glVertex2f, "Float", KeyBW2, "Float", 10/4*2.5)
DllCall(glVertex2f, "Float", -KeyBW2, "Float", 10/4*2.5)
DllCall(glColor4f, "Float", 0.1, "Float", 0.1, "Float", 0.1, "Float", 1)
DllCall(glVertex2f, "Float", -KeyBW4, "Float", 0.5)
DllCall(glVertex2f, "Float", KeyBW4, "Float", 0.5)
DllCall(glColor4f, "Float", 0.25, "Float", 0.25, "Float", 0.25, "Float", 1)
DllCall(glVertex2f, "Float", KeyBW4, "Float", 10/4*2.0)
DllCall(glVertex2f, "Float", -KeyBW4, "Float", 10/4*2.0)
DllCall(glColor4f, "Float", 0.1, "Float", 0.1, "Float", 0.1, "Float", 1)
DllCall(glVertex2f, "Float", -KeyBW4, "Float", 0.5)
DllCall(glVertex2f, "Float", KeyBW4, "Float", 0.5)
DllCall(glColor4f, "Float", 0.25, "Float", 0.25, "Float", 0.25, "Float", 1)
DllCall(glVertex2f, "Float", KeyBW2, "Float", 0)
DllCall(glVertex2f, "Float", -KeyBW2, "Float", 0)
DllCall(glColor4f, "Float", 0.15, "Float", 0.15, "Float", 0.15, "Float", 1)
DllCall(glVertex2f, "Float", -KeyBW4, "Float", 10/4*2.0)
DllCall(glVertex2f, "Float", KeyBW4, "Float", 10/4*2.0)
DllCall(glColor4f, "Float", 0.1, "Float", 0.1, "Float", 0.1, "Float", 1)
DllCall(glVertex2f, "Float", KeyBW2, "Float", 10/4*2.5)
DllCall(glVertex2f, "Float", -KeyBW2, "Float", 10/4*2.5)
DllCall(glEnd)
DllCall(glEndList)

PointSize := 1
DllCall(glNewList, "UInt", List+5, "UInt", GL_COMPILE)
DllCall(glEnable, "UInt", GL_BLEND)
DllCall(glBegin, "UInt", GL_TRIANGLES)
DllCall(glColor4f, "Float", 1, "Float", 0, "Float", 0, "Float", 1)
DllCall(glVertex2f, "Float", 0, "Float", 0)
DllCall(glColor4f, "Float", 1, "Float", 0, "Float", 0, "Float", 0)
DllCall(glVertex2f, "Float", 0, "Float", PointSize)
DllCall(glVertex2f, "Float", Sin(10.0531)*PointSize, "Float", -(Cos(10.0531)*PointSize))
DllCall(glEnd)
DllCall(glDisable, "UInt", GL_BLEND)
DllCall(glEndList)

DllCall(glNewList, "UInt", List+6, "UInt", GL_COMPILE)
DllCall(glTranslatef, "Float", 0, "Float", 8, "Float", 0)
DllCall(glScalef, "Float", 1.2, "Float", 1, "Float", 1)
Loop, 10
	{
	DllCall(glCallList, "UInt", List+5)
	DllCall(glRotatef, "Float", 36, "Float", 0, "Float", 0, "Float", 1)
	}
DllCall(glEndList)
FontOut := DllCall(glGenLists, "UInt", charR)
FontIn := DllCall(glGenLists, "UInt", charR)
hFont := DllCall("gdi32\CreateFont" AW
	, "Int", -1
	, "Int", 0
	, "Int", 0
	, "Int", 0
	, "Int", 800
	, "UInt", 0
	, "UInt", 0
	, "UInt", 0
	, "UInt", 0
	, "UInt", 4
	, "UInt", 0
	, "UInt", 4
	, "UInt", 0
	, "Ptr", 0
	, "Ptr")
hOFont := DllCall("gdi32\SelectObject", "Ptr", hDC, "Ptr", hFont, "Ptr")
VarSetCapacity(gmf, charR*24, 0)	; GLYPHMETRICSFLOAT struct
DllCall("opengl32\wglUseFontOutlines" AW
	, "Ptr", hDC
	, "UInt", charL
	, "UInt", charR
	, "UInt", FontOut
	, "Float", 0
	, "Float", 0.2
	, "Int", 0
	, "Ptr", &gmf)
DllCall("opengl32\wglUseFontOutlines" AW
	, "Ptr", hDC
	, "UInt", charL
	, "UInt", charR
	, "UInt", FontIn
	, "Float", 0
	, "Float", 0.2
	, "Int", 1
	, "Ptr", 0)
Gui, 2:Show, w%KbdW% h%KbdH%, Virtual keyboard
SetTimer, UpdateOpenGL, 50
Return

UpdateOpenGL:
Critical
DllCall(glClear, "UInt", GL_COLOR_BUFFER_BIT)
DllCall(glViewport, "Int", 0, "Int", 0, "Int", KbdW, "Int", KbdH)
DllCall(glMatrixMode, "UInt", GL_PROJECTION)
DllCall(glLoadIdentity)
DllCall(glOrtho, "Double", 0, "Double", 100, "Double", 10, "Double", 0, "Double", -1, "Double", 1)
DllCall(glMatrixMode, "UInt", GL_MODELVIEW)
DllCall(glLoadIdentity)
Index := 1, cOktav := 1
Loop, % NumKeys
	{
	If Index in 1,3,5,7,8,10,12
		{
		DllCall(glCallList, "UInt", ((KeyI%A_Index%down) ? List+3 : List+1))
		VK := GetKeyVK(Format("sc{:x}", MKey%A_Index%))
		If VK between %charL% and %charH%
			{
			DllCall(glPushMatrix)
			DllCall(glTranslatef, "Float", -(KeyWW*0.8), "Float", 9, "Float", 0)
			DllCall(glScalef, "Float", 3, "Float", -3, "Float",  1)
			DllCall(glPushMatrix)
			If (Index = 8 && cOktav = Oktav)
				DllCall(glColor4f, "Float", 1, "Float", 0.5, "Float", 0.5, "Float", 0.5)
			Else DllCall(glColor4f, "Float", 0.7, "Float", 0.7, "Float", 0.7, "Float", 0.5)
			DllCall(glEnable, "UInt", GL_BLEND)
			DllCall(glEnable, "UInt", GL_LINE_SMOOTH)
			DllCall(glCallList, "UInt", FontOut+VK-charL)
			DllCall(glDisable, "UInt", GL_LINE_SMOOTH)
			DllCall(glDisable, "UInt", GL_BLEND)
			DllCall(glPopMatrix)
			If (Index = 8 && cOktav = Oktav)
				DllCall(glColor4f, "Float", 1, "Float", 0.5, "Float", 0.5, "Float", 1)
			Else DllCall(glColor4f, "Float", 0.7, "Float", 0.7, "Float", 0.7, "Float", 1)
			DllCall(glCallList, "UInt", FontIn+VK-charL)
			DllCall(glPopMatrix)
			}
		}
	Index++
	if Index > 12
		{
		Index := 1
		cOktav--
		}
	}
DllCall(glLoadIdentity)
Index := 1
Loop, % NumKeys
	{
	If Index in 2,4,6,9,11
		DllCall(glCallList, "UInt", ((KeyI%A_Index%down) ? List+4 : List+2))
	If Index in 6,11
		DllCall(glTranslatef, "Float", KeyWW, "Float", 0, "Float", 0)
	Index++
	If Index > 12
		Index := 1
	}
;DllCall(glLoadIdentity)
;DllCall(glTranslatef, "Float", KeyWW*4.5, "Float", 0, "Float", 0)
;DllCall(glCallList, "UInt", List+6)
DllCall(SwapBuffers, "Ptr", hDC)
Return
Last edited by Drugwash on 18 Apr 2018, 16:41, edited 1 time in total.
Part of my AHK work can be found here.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI: piano keyboard

18 Apr 2018, 14:55

- With your new script, the keys play, but as before the GUI keyboard subwindow displays, but the keyboard doesn't show, before it just wasn't drawn, now it appears as a black rectangle. Also, I had to remove the 'updates' function.
- Well done on your tweaks to AutoHotkey Basic.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: GUI: piano keyboard

18 Apr 2018, 15:24

Ouch, updates() is necessary for AW and A_CharSize, I'm so used to it here that I forgot to replace it with the declarations as in previous version. If you do that locally maybe it'll start working correctly.
(my head is messed up by a sudden cold, sorry for these issues)
Part of my AHK work can be found here.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI: piano keyboard

18 Apr 2018, 15:36

So use this?
A_CharSize := 1
AW := "A"
The keyboard GUI was still blank.
And the Device drop-down list was showing all Chinese characters.
And pressing keys to play notes stopped working.
Try comparing older scripts with my newer script using WinMerge.
We need to avoid ending up like KeypressOSD with updates twice a day.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: GUI: piano keyboard

18 Apr 2018, 15:47

AW := A_IsUnicode ? "W" : "A", A_CharSize := A_IsUnicode ? 2 : 1 ; these can be found in some newer scripts of mine, in updates.ahk
It's in previous version above. What you put above would only work for ANSI AHK.

I looked through your code and the visible diferences were in some data types, Int vs UInt.
If I had an x64 machine it probably would've been fixed already; since I don't, I'm shooting in the dark.

off-topic:
Keypress has opened a whole can of worms, problems are deeper that they may appear and it's not (only) the code, it's the OS itself, maybe even MSKLC or any tools that have been used to create certain layouts that do not behave like the older ones and so on. The only problem is with dead keys and their combination, but that's enough to mess things up badly.
Part of my AHK work can be found here.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI: piano keyboard

18 Apr 2018, 16:27

I tried:
AW := A_IsUnicode ? "W" : "A"
A_CharSize := A_IsUnicode ? 2 : 1
And got the same results as before, black where the keyboard is, but keys working.

I fixed the line starting 'glNewList := DllCall', and your script worked.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: GUI: piano keyboard

18 Apr 2018, 16:35

OK, thank you. I need a new pair of eyes because the glasses don't help anymore.
Glad it finally works. Cheers!
Part of my AHK work can be found here.
User avatar
SpeedMaster
Posts: 494
Joined: 12 Nov 2016, 16:09

Re: GUI: piano keyboard

19 Apr 2018, 07:47

Many thanks for all the improvements you have made. :bravo:
The US keyboard was falsely generated by my french AZERTY keyboard (I forgot to switch to US keys :facepalm: ). :?
In fact it seems that both US and UK keyboards are generating exactly the same code. (not tested with real US keyboard) :)
I updated my previous download post with the 2 versions. :thumbup:



Cheers
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: GUI: piano keyboard

19 Apr 2018, 09:22

Merci beaucoup. :)
Hopefully the scancode system will fit any possible layout without the need for tweaking the code. All that remains is to have the user choose the proper layout so the characters displayed on the keys would fit those on the physical keyboard (regardless of the software layout chosen for the system/application).
Unfortunately I spent all day on a wild goose chase today, otherwise I might have improved it more. But there's still time. ;)
Part of my AHK work can be found here.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: catquas, jpsala and 166 guests