Page 14 of 105 FirstFirst ... 4111213141516172464 ... LastLast
Results 521 to 560 of 4199

Thread: CommonControls (Replacement of the MS common controls)

  1. #521
    Fanatic Member DrUnicode's Avatar
    Join Date
    Mar 2008
    Location
    Natal, Brazil
    Posts
    631

    Re: CommonControls (Replacement of the MS common controls)

    U.S. Keyboard will not join ~ and a.
    U.S. International will join them and print ã.
    "Tilde" is to the left of Number 1 on U.S. International keyboard. Use shift to get it and then follow it with "a".
    Try this in Notepad first.
    Once you confirm this, try same in UniTextBox.

    U.S. International layout (OnScreenKeyboard):

    Name:  U.S. International.jpg
Views: 5394
Size:  29.2 KB
    Last edited by DrUnicode; Nov 8th, 2014 at 01:32 PM. Reason: Screenshot

  2. #522
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,309

    Re: CommonControls (Replacement of the MS common controls)

    Join as we speak, but this ã is another unicode char.

  3. #523

    Thread Starter
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,728

    Re: CommonControls (Replacement of the MS common controls)

    Does not work by me...

  4. #524
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,309

    Re: CommonControls (Replacement of the MS common controls)

    Name:  usinternational.jpg
Views: 5191
Size:  35.6 KB

    In Xp those keys are blue...(here in red circles)

  5. #525
    Fanatic Member DrUnicode's Avatar
    Join Date
    Mar 2008
    Location
    Natal, Brazil
    Posts
    631

    Re: CommonControls (Replacement of the MS common controls)

    Does not work by me...
    Does it work in Notepad but not in UniTextBox?

  6. #526
    Fanatic Member DrUnicode's Avatar
    Join Date
    Mar 2008
    Location
    Natal, Brazil
    Posts
    631

    Re: CommonControls (Replacement of the MS common controls)

    This is with U.S. International:

    Name:  UniTextBox ã U.S. International.jpg
Views: 5182
Size:  31.2 KB

    This is with ABNT2 Brazilian Portuguese:

    Name:  UniTextBox ã ABNT2 Portuguese.jpg
Views: 5179
Size:  35.1 KB

  7. #527

    Thread Starter
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,728

    Re: CommonControls (Replacement of the MS common controls)

    Ok, it seems to work now. Can anyone else check it out. By replacing the code in my TextBox as following:

    Code:
    Private TextBoxKeyCodeCache As Integer, TextBoxDeadKeyCodeCache As Integer
    Code:
        Case WM_KEYDOWN, WM_KEYUP
            Dim KeyCode As Integer
            KeyCode = wParam And &HFF&
            If wMsg = WM_KEYDOWN Then
                RaiseEvent KeyDown(KeyCode, GetShiftState())
                If IsDeadKey(KeyCode) = True  And TextBoxDeadKeyCodeCache = 0 Then TextBoxDeadKeyCodeCache = KeyCode
                TextBoxKeyCodeCache = KeyCode
            ElseIf wMsg = WM_KEYUP Then
                RaiseEvent KeyUp(KeyCode, GetShiftState())
            End If
            wParam = KeyCode
        Case WM_CHAR
            Dim KeyChar As Integer, UniChar As String
            If TextBoxKeyCodeCache <> 0 Then
                If TextBoxDeadKeyCodeCache <> 0 Then
                    KeyCodeToUniChar TextBoxDeadKeyCodeCache
                    TextBoxDeadKeyCodeCache = 0
                End If
                UniChar = KeyCodeToUniChar(TextBoxKeyCodeCache)
                If Len(UniChar) > 1 Then
                    TextBoxKeyCodeCache = CUIntToInt(AscW(Mid$(UniChar, 2, 1)))
                Else
                    TextBoxKeyCodeCache = 0
                End If
            End If
            If Len(UniChar) > 0 Then
                KeyChar = CUIntToInt(AscW(UniChar))
            Else
                KeyChar = CUIntToInt(wParam And &HFFFF&)
            End If
            RaiseEvent KeyPress(KeyChar)
            If (wParam And &HFFFF&) <> 0 And KeyChar = 0 Then
                Exit Function
            Else
                wParam = CIntToUInt(KeyChar)
            End If
    Code:
    Private Declare Function MapVirtualKey Lib "user32" Alias "MapVirtualKeyW" (ByVal uCode As Long, ByVal uMapType As Long) As Long
    Private Declare Function GetKeyboardLayout Lib "user32" (ByVal dwThreadID As Long) As Long
    Private Declare Function GetKeyboardState Lib "user32" (ByRef pbKeyState As Byte) As Long
    Private Declare Function ToUnicodeEx Lib "user32" (ByVal uVirtKey As Long, ByVal uScanCode As Long, ByRef lpKeyState As Byte, ByVal lpwszBuffer As Long, ByVal cchBuffer As Long, ByVal wFlags As Long, ByVal hKL As Long) As Long
    
    Public Function KeyCodeToUniChar(ByVal KeyCode As Integer) As String
    Dim Buffer As String, BufferPtr As Long, B(0 To 255) As Byte, RetVal As Long
    Buffer = String$(32, vbNullChar)
    BufferPtr = StrPtr(Buffer)
    GetKeyboardState B(0)
    RetVal = ToUnicodeEx(KeyCode, 0, B(0), BufferPtr, Len(Buffer), 0, GetKeyboardLayout(0))
    SysReAllocString VarPtr(KeyCodeToUniChar), BufferPtr
    End Function
    
    Public Function IsDeadKey(ByVal KeyCode As Integer) As Boolean
    Const MAPVK_VK_TO_CHAR As Long = &H2
    IsDeadKey = CBool(MapVirtualKey(KeyCode, MAPVK_VK_TO_CHAR) < 0)
    End Function
    Last edited by Krool; Nov 8th, 2014 at 03:05 PM.

  8. #528
    Fanatic Member DrUnicode's Avatar
    Join Date
    Mar 2008
    Location
    Natal, Brazil
    Posts
    631

    Re: CommonControls (Replacement of the MS common controls)

    With your changes I'm getting "à" instead of "ã" with U.S. International keyboard.
    What is strange is that I get this Grave accent both with and without shift.

    BTW - I tried my original code also in your control and it worked OK, even with "ã".

  9. #529
    Fanatic Member DrUnicode's Avatar
    Join Date
    Mar 2008
    Location
    Natal, Brazil
    Posts
    631

    Re: CommonControls (Replacement of the MS common controls)

    I don't know if this helps but if you hold the Shift Key, press Tilde and then "A" you get "Ã"
    but if you release the shift after tilde you get "à" in lieu of "ã".

  10. #530

    Thread Starter
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,728

    Re: CommonControls (Replacement of the MS common controls)

    Quote Originally Posted by DrUnicode View Post
    With your changes I'm getting "à" instead of "ã" with U.S. International keyboard.
    What is strange is that I get this Grave accent both with and without shift.

    BTW - I tried my original code also in your control and it worked OK, even with "ã".
    Can you please show me your source code implemented into my TextBox? (couldn't get it work by me straight from your original code)

  11. #531

    Thread Starter
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,728

    Re: CommonControls (Replacement of the MS common controls)

    I found the reason. I skipped the following from your original code:
    Code:
       If Not IsUnicode(ToCharacterEx) Then 'This may not be necessary
          ToCharacterEx = ChrW$(KeyAscii)
       End If
    As I thought that this is not necessary. However, it actually is..

  12. #532
    Fanatic Member DrUnicode's Avatar
    Join Date
    Mar 2008
    Location
    Natal, Brazil
    Posts
    631

    Re: CommonControls (Replacement of the MS common controls)

    Attached is IME code in your control.
    Attached Zip has only TextBoxW.ctl and Common.bas, the only 2 file that were modified.
    Attached Files Attached Files

  13. #533
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,309

    Re: CommonControls (Replacement of the MS common controls)

    To many lines to make it to work. With much of research I found that the use of GetLastKeyPressed is what we need to do the job right.
    These works for me...and I think that can be work for you too...If a key give two or more wchars then with GetLastKeyPressed you don't need to interpret what it is interpreted for you...and in the right way...

    Code:
    dim UKEY$
    Private Declare Function GetLocaleInfo Lib "kernel32" Alias "GetLocaleInfoW" (ByVal Locale As Long, ByVal LCType As Long, ByVal lpLCData As Long, ByVal cchData As Long) As Long
    Private Declare Function GetKeyboardLayout& Lib "user32" (ByVal dwLayout&) ' not NT?
    Private Const DWL_ANYTHREAD& = 0
    Const LOCALE_ILANGUAGE = 1
    Const WM_KEYFIRST = &H100  ' I have no idea why keyfirst must be &h100
     Const WM_KEYLAST = &H108
     Private Type POINTAPI
        X As Long
        Y As Long
    End Type
     Private Type Msg
        hwnd As Long
        Message As Long
        wParam As Long
        lParam As Long
        time As Long
        pt As POINTAPI
    End Type
    Public Function GetLastKeyPressed() As Long
    ' no subclass
    ' we have one keyboard only so in the keydown...99.99% we get the keystroke
    Dim Message As Msg
        If PeekMessageW(Message, 0, WM_KEYFIRST, WM_KEYLAST, 0) Then
            GetLastKeyPressed = Message.wParam
        Else
            GetLastKeyPressed = -1
        End If
        Exit Function
    End Function
    
    Function GetKeY(ascii As Integer) As String
        Dim Buffer As String, Ret As Long. r as long
        Buffer = String$(514, 0)
          r = GetKeyboardLayout(DWL_ANYTHREAD) And &HFFFF
          r = Val("&H" & Right(Hex(r), 4))
        Ret = GetLocaleInfo(r, LOCALE_ILANGUAGE, StrPtr(Buffer), Len(Buffer))
        If Ret > 0 Then
            GetKeY = ChrW$(AscW(StrConv(ChrW$(ascii Mod 256), 64, CLng(Val("&h" + Left$(Buffer, Ret - 1))))))
        Else
            GetKeY = ChrW$(AscW(StrConv(ChrW$(ascii Mod 256), 64, 1033)))
        End If
    End Function
    
    
    
    in keydown event
    .........code for arrows and special keys
    I = GetLastKeyPressed
     If I <> -1 And I <> 94 Then UKEY$ = ChrW(I) Else UKEY$ = ""
    
    
    in keypress event
    ..................code for other keys...
     If EditFlag And KeyAscii > 32 And KeyAscii <> 127 Then
                If UKEY$ <> "" Then
                kk$ = UKEY$
                Else
      kk$ = GetKeY(KeyAscii)   ' this was the old way...I didn't deleted...If UKEY$ didn't work (if GetLastKeyPresserd give always -1, we can write...)
      End If
                 RaiseEvent RemoveOne(kk$)   ' this is for undo
                If SelStart = 0 Then mSelstart = 1
               
                SelStartEventAlways = SelStart + 1
       
                    List(SELECTEDITEM - 1) = Left$(List(SELECTEDITEM - 1), SelStart - 2) + kk$ + Mid$(List(SELECTEDITEM - 1), SelStart - 1)
                
             
                End If
             End If
    With GetKey we can get the unicode from ascii...reading the keyboard localeid...but we miss the dead keys and double chars...
    Now we have both...because we read the unicode value before. With the addition of Unicode No 94 as the dead key indicator..we are complete
    In my control there is no RTB or other control..from third party. In fact there are no other control but the user control only, and three shapes for constructing the scroll bar.
    Last edited by georgekar; Nov 8th, 2014 at 04:03 PM.

  14. #534

    Thread Starter
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,728

    Re: CommonControls (Replacement of the MS common controls)

    I finally got it now to work, the solution was to save the keystate of the dead key.

    @ DrUnicode, can you please test again on your side?

    Code:
    Private Declare Function GetKeyboardState Lib "user32" (ByRef pbKeyState As Byte) As Long
    
    Private TextBoxKeyCodeCache As Integer, TextBoxDeadKeyCodeCache As Integer, TextBoxDeadKeyState(0 To 255) As Byte
    Code:
        Case WM_KEYDOWN, WM_KEYUP
            Dim KeyCode As Integer
            KeyCode = wParam And &HFF&
            If wMsg = WM_KEYDOWN Then
                RaiseEvent KeyDown(KeyCode, GetShiftState())
                TextBoxKeyCodeCache = KeyCode
                If IsDeadKey(KeyCode) = True And TextBoxDeadKeyCodeCache = 0 Then
                    TextBoxDeadKeyCodeCache = KeyCode
                    GetKeyboardState TextBoxDeadKeyState(0)
                End If
            ElseIf wMsg = WM_KEYUP Then
                RaiseEvent KeyUp(KeyCode, GetShiftState())
            End If
            wParam = KeyCode
        Case WM_CHAR
            Dim KeyChar As Integer, UniChar As String
            If TextBoxKeyCodeCache <> 0 Then
                Dim ScanCode As Integer, B(0 To 255) As Byte
                ScanCode = LoByte(HiWord(lParam))
                If TextBoxDeadKeyCodeCache <> 0 Then
                    KeyCodeToUniChar TextBoxDeadKeyCodeCache, ScanCode, TextBoxDeadKeyState()
                    TextBoxDeadKeyCodeCache = 0
                End If
                GetKeyboardState B(0)
                UniChar = KeyCodeToUniChar(TextBoxKeyCodeCache, ScanCode, B())
                TextBoxKeyCodeCache = 0
            End If
            If Len(UniChar) > 0 Then
                KeyChar = CUIntToInt(AscW(UniChar))
            Else
                KeyChar = CUIntToInt(wParam And &HFFFF&)
            End If
            RaiseEvent KeyPress(KeyChar)
            If (wParam And &HFFFF&) <> 0 And KeyChar = 0 Then
                Exit Function
            Else
                wParam = CIntToUInt(KeyChar)
            End If
    Code:
    Private Declare Function MapVirtualKey Lib "user32" Alias "MapVirtualKeyW" (ByVal uCode As Long, ByVal uMapType As Long) As Long
    Private Declare Function GetKeyboardLayout Lib "user32" (ByVal dwThreadID As Long) As Long
    Private Declare Function ToUnicodeEx Lib "user32" (ByVal uVirtKey As Long, ByVal uScanCode As Long, ByRef lpKeyState As Byte, ByVal lpwszBuffer As Long, ByVal cchBuffer As Long, ByVal wFlags As Long, ByVal hKL As Long) As Long
    
    Public Function KeyCodeToUniChar(ByVal KeyCode As Integer, ByVal ScanCode As Integer, ByRef B() As Byte) As String
    Dim Buffer As String, BufferPtr As Long, RetVal As Long
    Buffer = String$(32, vbNullChar)
    BufferPtr = StrPtr(Buffer)
    RetVal = ToUnicodeEx(KeyCode, ScanCode, B(0), BufferPtr, Len(Buffer), 0, GetKeyboardLayout(0))
    SysReAllocString VarPtr(KeyCodeToUniChar), BufferPtr
    End Function
    
    Public Function IsDeadKey(ByVal KeyCode As Integer) As Boolean
    Const MAPVK_VK_TO_CHAR As Long = &H2
    IsDeadKey = CBool(MapVirtualKey(KeyCode, MAPVK_VK_TO_CHAR) < 0)
    End Function

  15. #535
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,309

    Re: CommonControls (Replacement of the MS common controls)

    If someone press ' twice then the second time he has to get these ' two times.

  16. #536
    Fanatic Member DrUnicode's Avatar
    Join Date
    Mar 2008
    Location
    Natal, Brazil
    Posts
    631

    Re: CommonControls (Replacement of the MS common controls)

    @ DrUnicode, can you please test again on your side?
    Yes. All working fine now. Tested Kazakh, U.S. Normal, U.S. International.

    Did you remove this piece of code?
    Code:
    If Len(UniChar) > 1 Then
       TextBoxKeyCodeCache = CUIntToInt(AscW(Mid$(UniChar, 2, 1)))
    I think you may need it for IME that generates 2 Unicode characters for single keystroke.
    I can't remember which IME I tested this with because it was 9 years ago.

  17. #537

    Thread Starter
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,728

    Re: CommonControls (Replacement of the MS common controls)

    Quote Originally Posted by DrUnicode View Post
    Did you remove this piece of code?
    Code:
    If Len(UniChar) > 1 Then
       TextBoxKeyCodeCache = CUIntToInt(AscW(Mid$(UniChar, 2, 1)))
    I think you may need it for IME that generates 2 Unicode characters for single keystroke.
    I can't remember which IME I tested this with because it was 9 years ago.
    Yes I removed that. Because 2 Unicode characters by a single keystroke just happens when you press a dead key twice. (for e.g. pressing two times ^ will result in ^^ or 2x time WM_CHAR with key char ^)
    This case is also described in the MSDN page for the ToUnicode API. ("The most common cause for this is that a dead-key character (accent or diacritic) stored in the keyboard layout could not be combined with the specified virtual key to form a single character.")
    But in our case this cannot happen. (VB's main loop itself will produce the WM_CHAR).
    We just need to handle the case when a WM_CHAR is coming and previous key was a dead-key, in order to combine them.

    Another point: AscW returns a key char and not a key code. Thus this would also be wrong, no?
    Last edited by Krool; Nov 9th, 2014 at 04:33 AM.

  18. #538
    Fanatic Member DrUnicode's Avatar
    Join Date
    Mar 2008
    Location
    Natal, Brazil
    Posts
    631

    Re: CommonControls (Replacement of the MS common controls)

    Because 2 Unicode characters by a single keystroke just happens when you press a dead key twice.
    It was 9 years ago when I ran into this issue reported by a customer.
    Apparently a particular IME generated a surrogate pair, 2 Unicode characters for a single keystroke.
    In this case you don't get a WM_KEYDOWN for the second charcter but you do get another WM_CHAR.
    We need to find out which IME does this and which keystroke to test this.

  19. #539
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,309

    Re: CommonControls (Replacement of the MS common controls)

    Maybe I write for nothing..but...I have solve this problem. I can't work with the library of Krool because I found difficulties to run it in Xp.
    We can get the pressing keys as unicode string before the keypress event..So we have to take these keys in a string and use it in the keypress event. So we need a string as buffer, as a variable declared for module/class/form/user control...The last pressing key return -1 if we have no char...so we skip the writing to the buffer. If we have a number 94 then that is ANY dead key (in any combination, so we don't have to read Shift state), and we just SKIP the buffer writing. In Keypress event we process the buffer if the key that supposed to give is a key in the range of keys and not delete or other<32 (in my control ascii code 32 is used for two things so I have to exclude it).
    So how we get two or more keystrokes that produce ONE unicode code? Easy as you see, because we read the final Unicode code (so this is done from os for us)...and not the intermediate keystrokes. If you wish to write the OS again then make your own code..but in that situation..do not use the ready made control from MS...make your own, you will be happy too. You can leave the original messages (by raising events prior the right process) to give external process for the final user...and check for changes to values and then "skip" the right process if you found any (because this process are not known to the final user).
    Last edited by georgekar; Nov 9th, 2014 at 06:20 AM. Reason: language..problem

  20. #540

    Thread Starter
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,728

    Re: CommonControls (Replacement of the MS common controls)

    Quote Originally Posted by DrUnicode View Post
    It was 9 years ago when I ran into this issue reported by a customer.
    Apparently a particular IME generated a surrogate pair, 2 Unicode characters for a single keystroke.
    In this case you don't get a WM_KEYDOWN for the second charcter but you do get another WM_CHAR.
    We need to find out which IME does this and which keystroke to test this.
    Ok, then following way would solve it. (Though I cannot test)
    Code:
        Case WM_CHAR
            Static SurrogateKeyChar As Integer
            Dim KeyChar As Integer, UniChar As String
            If TextBoxKeyCodeCache <> 0 Then
                If TextBoxDeadKeyCodeCache <> 0 Then
                    KeyCodeToUnicode TextBoxDeadKeyCodeCache, TextBoxDeadScanCodeCache, TextBoxDeadKeyStateCache()
                    TextBoxDeadKeyCodeCache = 0
                End If
                Dim KeyState(0 To 255) As Byte
                GetKeyboardState KeyState(0)
                UniChar = KeyCodeToUnicode(TextBoxKeyCodeCache, HiWord(lParam), KeyState())
                TextBoxKeyCodeCache = 0
            End If
            If Len(UniChar) > 0 Then
                KeyChar = CUIntToInt(AscW(UniChar))
                If Len(UniChar) > 1 Then SurrogateKeyChar = CUIntToInt(AscW(Mid$(UniChar, 2, 1)))
            Else
                If SurrogateKeyChar <> 0 Then
                    KeyChar = SurrogateKeyChar
                    SurrogateKeyChar = 0
                Else
                    KeyChar = CUIntToInt(wParam And &HFFFF&)
                End If
            End If
            RaiseEvent KeyPress(KeyChar)

  21. #541

    Thread Starter
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,728

    Re: CommonControls (Replacement of the MS common controls)

    But still there is one important issue.
    Open notepad and any of your Unicode TextBox. When you enter a dead key now in the notepad, for e.g. `. Then switch to the Unicode TextBox and enter the the 'a' character. Do you get 'à' or just 'a'? Same vice versa. The notepad does it correctly, seems like it somehow knows that a dead key was pressed before.

    But I think in DrUnicode version this is not a problem due to the last thing "If Not IsUnicode(ToCharacterEx) Then" fixes this issue. But for me that is not a proper way.

  22. #542
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: CommonControls (Replacement of the MS common controls)

    Nice work making progress on this! While we're talking about dead keys, here's another language to test: Vietnamese. The Vietnamese keyboard works a little differently because regular letters can function as dead keys, but only if they are followed by certain characters.

    For example: in Notepad, typing 1 gives you:

    ă

    Typing 1 and then 9 erases that character, and replaces it with:

    ặ

    Similarly, typing 1 and then 8 gives you:

    ắ

    So that initial ă can be merged with a number of other diacritics, or it can be used as a standalone character. This is different from other dead keys because the first character appears when pressed, and it's only treated as a dead key if a subsequent key modifies it in some way. Hopefully your existing code works with these as well!

    @Krool:

    "The notepad does it correctly, seems like it somehow knows that a dead key was pressed before."
    ToUnicode, for better or worse, uses the global (kernel-mode) key buffer to assemble keystrokes. So a dead key typed in one window will affect the ToUnicode buffer in another window. It's part of what makes ToUnicode so difficult to use, because every time you call it, it rewrites the global key buffer, so trying to use it from a hook (for example) can prevent other windows from receiving the correct keystrokes.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  23. #543
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: CommonControls (Replacement of the MS common controls)

    Quote Originally Posted by DrUnicode View Post
    It was 9 years ago when I ran into this issue reported by a customer.
    Apparently a particular IME generated a surrogate pair, 2 Unicode characters for a single keystroke.
    In this case you don't get a WM_KEYDOWN for the second charcter but you do get another WM_CHAR.
    We need to find out which IME does this and which keystroke to test this.
    Could we test this with direct entry using the Alt key? For example, Alt+173 569 should produce the surrogate pair character 𪘁.

    I haven't tested yet, but I'm not sure whether this still causes two WM_CHAR messages to be raised. What's strange is that Notepad doesn't handle this kind of Alt+key input correctly. (It produces a ☺character.) However, WordPad correctly produces 𪘁.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  24. #544
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,167

    Re: CommonControls (Replacement of the MS common controls)

    Quote Originally Posted by Krool View Post
    But still there is one important issue.
    Open notepad and any of your Unicode TextBox. When you enter a dead key now in the notepad, for e.g. `. Then switch to the Unicode TextBox and enter the the 'a' character. Do you get 'à' or just 'a'? Same vice versa. The notepad does it correctly, seems like it somehow knows that a dead key was pressed before.
    I'm positive Notepad knows nothing of this and doesn't need to mess with key down/up at all. It just uses the unicode version of the standard Edit windows control *and* has a unicode message pump as the main app loop (GetMessageW/DispatchMessageW). This way on WM_CHAR it does get a unicode character in wParam in the lower 16-bits (not only the lower 8-bits as in VB6).

    VB6 run-time uses PeekMessageA/DispatchMessageA in the main msg pump, so even unicode hWnds (those created with CreateWindowExW or those with "unicode" wndproc set with SetWindowLongW) get a strippped down wParam on WM_CHAR -- the OS has done a Unicode to ACP (current system code page for non-unicode application) conversion on their behalf. And I doubt there is a reliable way to revert this conversion from ACP to Unicode once the damage is done.

    You have to intercept WM_CHAR earlier, in case of VB6 dispatched messages in the control's wndproc it is already too late to take counter measures. I've tested CyberActiveX's Unicode rich-textbox (the free download) and it is not working with my keyboard (I'm a native Bulgarian using cyrillic alphabet with a twist -- almost like Kazakh one) -- unicode input get converted to ? both in the IDE and compiled. I can take screenshots, videos, whatever to prove it :-))

    cheers,
    </wqw>

  25. #545
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,309

    Re: CommonControls (Replacement of the MS common controls)

    In post 533 I display that:
    ..........
    If PeekMessageW(Message, 0, WM_KEYFIRST, WM_KEYLAST, 0) Then
    GetLastKeyPressed = Message.wParam
    Else
    GetLastKeyPressed = -1
    End If
    Exit Function
    ...........
    And now in 544..we read it again...

  26. #546
    Fanatic Member DrUnicode's Avatar
    Join Date
    Mar 2008
    Location
    Natal, Brazil
    Posts
    631

    Re: CommonControls (Replacement of the MS common controls)

    Using English iInternational I can type "`" in Notepad and "a" in UniTextBox and I get the combined "à" in UniTextBox.
    Same for keyboard ABNT2 Portuguese, type "~" in Notepad and "a" in UniTextBox and I get "â" in UniTextBox.
    In both cases it works the other way around, accent in UniTextBox and "a" in Notepad gives "á" or "ã".

    Tanner_H
    Vietnamese:
    In UniTextBox I get the correct character with 1, 1+9, 1+8
    ă
    ặ
    ắ

    In ComCtldemo I also get:
    ă
    ặ
    ắ

    wqweto I've tested CyberActiveX's Unicode rich-textbox (the free download) and it is not working with my keyboard (I'm a native Bulgarian using cyrillic alphabet with a twist
    There are 2 RichEdit controls that we distribute:
    One is UniRichEdit_BDC0849A.ocx, a wrapper for vbRichTextBox and we would not expect it to handle IME correctly.
    The full Unicode version is UniRichEdit100_EDA1811C.ocx. This is the one that handles IME using same technique as UniTextBox.
    You need to download UniSuitePlus to get this control.
    UniTextBox is part of UniSuitePlus_BDC0849A.ocx which has 27 controls as a single ocx.

  27. #547
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: CommonControls (Replacement of the MS common controls)

    Quote Originally Posted by wqweto View Post
    I'm positive Notepad knows nothing of this and doesn't need to mess with key down/up at all. It just uses the unicode version of the standard Edit windows control *and* has a unicode message pump as the main app loop (GetMessageW/DispatchMessageW). This way on WM_CHAR it does get a unicode character in wParam in the lower 16-bits (not only the lower 8-bits as in VB6).

    VB6 run-time uses PeekMessageA/DispatchMessageA in the main msg pump, so even unicode hWnds (those created with CreateWindowExW or those with "unicode" wndproc set with SetWindowLongW) get a strippped down wParam on WM_CHAR -- the OS has done a Unicode to ACP (current system code page for non-unicode application) conversion on their behalf. And I doubt there is a reliable way to revert this conversion from ACP to Unicode once the damage is done.
    I think we covered this ground a bit earlier in the thread...

    The ToUnicode API *can* be used to reverse-engineer the missing Unicode char. It's not pretty, and you have to do some extra work to handle dead keys (because ToUnicode removes dead keys from the key buffer as it processes them). But it does work. No normal Unicode-aware program has reason to do this, because TranslateMessage (inside GetMessageW) typically does this for you. But you can access ToUnicode directly and perform your own virtual key to character translations.

    DrUnicode's solution (from Michael Kaplan, who literally wrote Microsoft's keyboard layout creator) handles this by waiting for WM_CHAR, then using ToUnicode to perform the same virtual key to Unicode translation that TranslateMessage normally would, using key state data cached during WM_KEYDOWN.

    I found it easier to perform the translation inside WM_KEYDOWN, then dispatch the correct WM_CHAR message(s) manually. Both of these methods produce the same Unicode output as a normal, W-aware message loop.

    This said, there *are* some situations you can't solve this way. As I just learned (in reference to my question about Alt+Unicode key values, above), Alt+# keypresses don't raise normal WM_KEYDOWN messages. They raise WM_SYSKEYDOWN messages, and ToUnicode doesn't handle the WM_CHAR translation. I don't know what does.

    So manual code is needed to cover this case, because WM_CHAR is indeed too late.

    But for "normal" key events (including IME), these methods do work. In fact, manual ToUnicode usage is the only way to convert keypresses to Unicode characters outside a normal message loop. (For example, a windowless program.)

    @DrUnicode - awesome, that's great news. I am also trying to track down an IME that produces surrogate pairs naturally (since we can't get them via Alt+numbers, as mentioned above). I'll let you know if I find one.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  28. #548

    Thread Starter
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,728

    Re: CommonControls (Replacement of the MS common controls)

    Thanks to georgekar, I have finally a perfect solution.

    Code:
    Private Type POINTAPI
    X As Long
    Y As Long
    End Type
    Private Type TMSG
    hWnd As Long
    Message As Long
    wParam As Long
    lParam As Long
    Time As Long
    PT As POINTAPI
    End Type
    Private Declare Function PeekMessage Lib "user32" Alias "PeekMessageW" (ByRef lpMsg As TMSG, ByVal hWnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As Long
    
    Public Function PeekCharCode(ByVal hWnd As Long) As Long
    Dim Msg As TMSG
    Const PM_NOREMOVE As Long = &H0, WM_CHAR As Long = &H102
    If PeekMessage(Msg, hWnd, WM_CHAR, WM_CHAR, PM_NOREMOVE) <> 0 Then PeekCharCode = Msg.wParam
    End Function
    That 'PeekCharCode' function I do call in the WM_KEYDOWN message and cache it in a variable.
    Then in the WM_CHAR message I cast this to back to wParam, but only in case the cache variable is <> 0.

    I tested and it seems to work good. Even globally with the dead chars and so on.

    Only issue might be the surrogate pairs, no? (But I don't know how to test this, since I do not know a sample) But in that case (surrogate pairs) the cached key char value would be 0 (due to no KeyDown before) but than the key char in WM_CHAR would be untouched. So at this point maybe not 100% but therefore the rest.

    EDIT: Update released
    Last edited by Krool; Nov 10th, 2014 at 04:07 AM.

  29. #549
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,167

    Re: CommonControls (Replacement of the MS common controls)

    Quote Originally Posted by Krool View Post
    Thanks to georgekar, I have finally a perfect solution.

    Code:
    Private Type POINTAPI
    X As Long
    Y As Long
    End Type
    Private Type TMSG
    hWnd As Long
    Message As Long
    wParam As Long
    lParam As Long
    Time As Long
    PT As POINTAPI
    End Type
    Private Declare Function PeekMessage Lib "user32" Alias "PeekMessageW" (ByRef lpMsg As TMSG, ByVal hWnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As Long
    
    Public Function PeekCharCode(ByVal hWnd As Long) As Long
    Dim Msg As TMSG
    Const PM_NOREMOVE As Long = &H0, WM_CHAR As Long = &H102
    If PeekMessage(Msg, hWnd, WM_CHAR, WM_CHAR, PM_NOREMOVE) <> 0 Then PeekCharCode = Msg.wParam
    End Function
    That 'PeekCharCode' function I do call in the WM_KEYDOWN message and cache it in a variable.
    Then in the WM_CHAR message I cast this to back to wParam, but only in case the cache variable is <> 0.

    I tested and it seems to work good. Even globally with the dead chars and so on.

    Only issue might be the surrogate pairs, no? (But I don't know how to test this, since I do not know a sample) But in that case (surrogate pairs) the cached key char value would be 0 (due to no KeyDown before) but than the key char in WM_CHAR would be untouched. So at this point maybe not 100% but therefore the rest.

    EDIT: Update released
    @Krool: This is seems like a solution to the problem, good you somehow deciphered georgekar thoughts :-)) The only missing part is if someone uses SendMessage to send WM_CHAR to your wndproc (on-screen keyboard, whatever) then you don't get a chance to peek it on WM_KEYDOWN, more I doubt the WM_CHAR message even gets in the message queue.

    Anyway, my proposal is to peek both ANSI *and* Unicode WM_CHARs (using both PeekMessageA and PeekMessageW one after another) and store these wParam's as an (ansi, unicode) pair for consecutive WM_CHAR handling. On WM_CHAR check if wParam is the ansi part of the pair and substitute with the unicode value, else leave wParam fall through.

    @DrUnicode: I noticed you are including an upgraded release of a project of mine in your UniSuite -- the UniHookMenu. At least you've seen my profile picture on PSC from something like 12 years ago :-)) Btw, I like control's icon w/ the hook -- Dread Pirate Roberts, no? :-))

    cheers,
    </wqw>

  30. #550

    Thread Starter
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,728

    Re: CommonControls (Replacement of the MS common controls)

    Quote Originally Posted by wqweto View Post
    @Krool: This is seems like a solution to the problem, good you somehow deciphered georgekar thoughts :-)) The only missing part is if someone uses SendMessage to send WM_CHAR to your wndproc (on-screen keyboard, whatever) then you don't get a chance to peek it on WM_KEYDOWN, more I doubt the WM_CHAR message even gets in the message queue.

    Anyway, my proposal is to peek both ANSI *and* Unicode WM_CHARs (using both PeekMessageA and PeekMessageW one after another) and store these wParam's as an (ansi, unicode) pair for consecutive WM_CHAR handling. On WM_CHAR check if wParam is the ansi part of the pair and substitute with the unicode value, else leave wParam fall through.
    In that case (sending WM_CHAR manually) the wParam value of the sendmessage function will be used. Because the cache variable is zero and therefore the value of wParam gets not altered. So only when doing a user input (KeyDown) the wParam value in WM_CHAR gets altered, and in addition only when there is a WM_CHAR in the pipe-line already. That way, in my opinion, makes it very fail-safe.
    Last edited by Krool; Nov 10th, 2014 at 12:27 PM.

  31. #551
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: CommonControls (Replacement of the MS common controls)

    Quote Originally Posted by wqweto View Post
    @Krool: This is seems like a solution to the problem, good you somehow deciphered georgekar thoughts :-)) The only missing part is if someone uses SendMessage to send WM_CHAR to your wndproc (on-screen keyboard, whatever) then you don't get a chance to peek it on WM_KEYDOWN, more I doubt the WM_CHAR message even gets in the message queue.
    Third-party applications that directly post Unicode character messages are hopefully using WM_UNICHAR. This allows the target window to respond to the first probe (with wParam = UNICODE_NOCHAR, or 0xffff) with a 1, meaning it can accept WM_UNICHAR messages.

    @Krool: it should be easy to add handling for WM_UNICHAR. In fact, aside from the UNICODE_NOCHAR case, you could probably just forward WM_UNICHAR messages to your existing WM_CHAR code, and have it work without trouble. (Though surrogate pairs might still require special handling...)
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  32. #552

    Thread Starter
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,728

    Re: CommonControls (Replacement of the MS common controls)

    Quote Originally Posted by Tanner_H View Post
    Third-party applications that directly post Unicode character messages are hopefully using WM_UNICHAR. This allows the target window to respond to the first probe (with wParam = UNICODE_NOCHAR, or 0xffff) with a 1, meaning it can accept WM_UNICHAR messages.

    @Krool: it should be easy to add handling for WM_UNICHAR. In fact, aside from the UNICODE_NOCHAR case, you could probably just forward WM_UNICHAR messages to your existing WM_CHAR code, and have it work without trouble. (Though surrogate pairs might still require special handling...)
    You mean like following?
    Code:
    Private Const WM_UNICHAR As Long = &H109, UNICODE_NOCHAR As Long = &HFFFF&
    
    Case WM_UNICHAR
        If wParam = UNICODE_NOCHAR Then WindowProcControl = 1 Else SendMessage hWnd, WM_CHAR, wParam, ByVal lParam
        Exit Function
    Last edited by Krool; Nov 11th, 2014 at 03:00 PM.

  33. #553
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: CommonControls (Replacement of the MS common controls)

    That looks good to me!

    BTW, thanks for all your great work, Krool. Really appreciate you sharing your controls.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  34. #554
    Member lrd_VB6's Avatar
    Join Date
    Jul 2014
    Location
    FRANCE
    Posts
    36

    Re: CommonControls (Replacement of the MS common controls)

    hello

    I slightly modified the control "Toolbar" because I thought it was not working properly.
    Especially the height that I was not correct.

    I was submiting your appobation but my tests are pretty conclusive.

    I retouched all routines using "TB_GETSTYLE" and especially "UserControl_Resize"

    What does the "TB_GETPADDING" because when I use the button size is wrong. (for me!).

    I ask the question again:
    Is it possible to have a control of the position "CommonDialog"?
    This would be very useful to me!

    kind regards

    Attachment 120825

  35. #555

    Thread Starter
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,728

    Re: CommonControls (Replacement of the MS common controls)

    Quote Originally Posted by lrd_VB6 View Post
    I slightly modified the control "Toolbar" because I thought it was not working properly.
    Especially the height that I was not correct.

    I was submiting your appobation but my tests are pretty conclusive.

    I retouched all routines using "TB_GETSTYLE" and especially "UserControl_Resize"

    What does the "TB_GETPADDING" because when I use the button size is wrong. (for me!).

    I ask the question again:
    Is it possible to have a control of the position "CommonDialog"?
    This would be very useful to me!
    I recommend the use of the CommonDialog class instead of a control in this case.
    But, you can "wrap" the COmmonDialog class into a new UserControl, for you special needs.

    For the ToolBar:
    You are correct. TB_GETPADDING is wrong. ("The padding values are used to create a blank area between the edge of the button and the button's image and/or text")
    And according to MSDN the divider line is always two-pixel. (CCS_NODIVIDER = "Prevents a two-pixel highlight from being drawn at the top of the control")
    I will fix this soon. Thanks
    Last edited by Krool; Nov 13th, 2014 at 03:45 PM.

  36. #556

    Thread Starter
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,728

    Re: CommonControls (Replacement of the MS common controls)

    Quote Originally Posted by DrUnicode View Post
    It was 9 years ago when I ran into this issue reported by a customer.
    Apparently a particular IME generated a surrogate pair, 2 Unicode characters for a single keystroke.
    In this case you don't get a WM_KEYDOWN for the second charcter but you do get another WM_CHAR.
    We need to find out which IME does this and which keystroke to test this.
    It would be good to know which IME and what key exactly generates two WM_CHARs.
    But the following would solve this case also?
    Code:
    Case WM_CHAR
        Dim KeyChar As Integer
        If TextBoxCharCodeCache <> 0 Then
            KeyChar = CUIntToInt(TextBoxCharCodeCache And &HFFFF&)
            TextBoxCharCodeCache = ComCtlsPeekCharCode(hWnd) ' Instead of 0&, look for another WM_CHAR in the pipeline.
        Else
            KeyChar = CUIntToInt(wParam And &HFFFF&)
        End If
    And I tried some tests with PostMessage and SendMessage with manually WM_KEYDOWN and WM_CHAR and the current implementation seems to be very fail-safe. I could not detect an error with this solution. (peek charcode in WM_KEYDOWN)

  37. #557
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,167

    Re: CommonControls (Replacement of the MS common controls)

    @Krool: Latest rich-textbox works with Bulgarian keyboard layout entering 'Shift+A' -- correctly produces ѝ (something like u with accent)

    cheers,
    </wqw>

  38. #558
    Fanatic Member DrUnicode's Avatar
    Join Date
    Mar 2008
    Location
    Natal, Brazil
    Posts
    631

    Re: CommonControls (Replacement of the MS common controls)

    It would be good to know which IME and what key exactly generates two WM_CHARs.
    But the following would solve this case also?
    Went through my old Emails but could not find the one that addresses this issue.

    Code:
    Case WM_CHAR
        Dim KeyChar As Integer
        If TextBoxCharCodeCache <> 0 Then
            KeyChar = CUIntToInt(TextBoxCharCodeCache And &HFFFF&)
            TextBoxCharCodeCache = ComCtlsPeekCharCode(hWnd) ' Instead of 0&, look for another WM_CHAR in the pipeline.
        Else
            KeyChar = CUIntToInt(wParam And &HFFFF&)
        End If
    This looks like it would solve the surrogate issue.

    Tested your latest build with several IME and all worked OK.
    Nice work.

  39. #559
    Member lrd_VB6's Avatar
    Join Date
    Jul 2014
    Location
    FRANCE
    Posts
    36

    Re: CommonControls (Replacement of the MS common controls)

    hello

    Too bad, I'm disappointed.
    You have not used the code that I had proposed in the attached zip file.
    I just tested the release and it does not work as well as mine.
    Roll style "Align = Top" a "Align = Left" and it becomes almost imposible to adjust the width !!
    I find your version a bit complicated but I have only tested on XP, so it may be there are things I do not know!

    I find the code:

    Code:
    Private Function ChangeStyle(ByVal bSetMask, Mask As Long) As Boolean
    Dim dwStyle As Long, NewStyle As Long
    
        If ToolBarHandle Then
            dwStyle = SendMessage(ToolBarHandle, TB_GETSTYLE, 0, ByVal 0&)
    
            If bSetMask Then
                NewStyle = dwStyle Or Mask
            Else
                NewStyle = dwStyle And Not Mask
            End If
    
            If dwStyle <> NewStyle Then
                SendMessage ToolBarHandle, TB_SETSTYLE, 0, ByVal NewStyle
                ChangeStyle = True
            End If
        End If
    
    End Function
    
    Public Property Let Divider(ByVal Value As Boolean)
        PropDivider = Value
    
        If ChangeStyle(Not PropDivider, CCS_NODIVIDER) Then
            SetWindowPos ToolBarHandle, 0, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOOWNERZORDER Or SWP_NOZORDER Or SWP_FRAMECHANGED
            UserControl_Resize
        End If
    
        UserControl.PropertyChanged "Divider"
    End Property
    easier to read than:
    Code:
    Public Property Let Divider(ByVal Value As Boolean)
        PropDivider = Value
    
        If ToolBarHandle <> 0 Then
    Dim dwStyle As Long
    
            dwStyle = SendMessage(ToolBarHandle, TB_GETSTYLE, 0, ByVal 0&)
    
            If PropDivider = True Then
                If (dwStyle And CCS_NODIVIDER) = CCS_NODIVIDER Then
                    SendMessage ToolBarHandle, TB_SETSTYLE, 0, ByVal dwStyle And Not CCS_NODIVIDER
                    SetWindowPos ToolBarHandle, 0, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOOWNERZORDER Or SWP_NOZORDER Or SWP_FRAMECHANGED
                End If
    
            Else
    
                If Not (dwStyle And CCS_NODIVIDER) = CCS_NODIVIDER Then
                    SendMessage ToolBarHandle, TB_SETSTYLE, 0, ByVal dwStyle Or CCS_NODIVIDER
                    SetWindowPos ToolBarHandle, 0, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOOWNERZORDER Or SWP_NOZORDER Or SWP_FRAMECHANGED
                End If
            End If
    
            Call UserControl_Resize
        End If
    
        UserControl.PropertyChanged "Divider"
    End Property

    Then my code version is "simpler" and does not have the default when you want to change the height or width if you change the property "Align"

    Code:
    Private Sub UserControl_Resize()
    Static InProc As Boolean
    
        If ToolBarHandle = 0 Then Exit Sub
    Dim dwStyle As Long
    Dim mWidth  As Single, mHeight As Single
    Dim mAlign  As VBRUN.AlignConstants
        If InProc Then Exit Sub
        InProc = True
        dwStyle = SendMessage(ToolBarHandle, TB_GETSTYLE, 0, ByVal 0&)
    
        With UserControl
            mAlign = .Extender.Align
    '
    'Align Change ?
    '
            If ChangeStyle(mAlign = vbAlignRight Or mAlign = vbAlignLeft, CCS_VERT) Then ' force resize Height or Width
    
                Select Case mAlign 
    
                    Case vbAlignTop, vbAlignBottom ', vbAlignNone
                        Me.Height = 10 
    
                    Case vbAlignLeft, vbAlignRight
                        Me.Width = 10
                End Select
    
            End If
    
            MoveWindow ToolBarHandle, 0, 0, .ScaleWidth, .ScaleHeight, 1 ' set size AND redraw for TB_AUTOSIZE calc
            SendMessage ToolBarHandle, TB_AUTOSIZE, 0, ByVal 0&
    
            GetIdealSize mWidth, mHeight
    '
    ' In GetIdealSize() Now
    '        If (dwStyle And CCS_NODIVIDER) = 0 Then
    '            mHeight = mHeight + .ScaleY(2, vbPixels, vbContainerSize)
    '        End If
    
            Select Case mAlign
    
                Case vbAlignTop, vbAlignBottom ', vbAlignNone
                    mWidth = Me.Width
    
                Case vbAlignLeft, vbAlignRight
                    mHeight = Me.Height
    
                Case Else
    'optional, force a minimum width or height
                    If Me.Height > mHeight Then mHeight = Me.Height
                    If Me.Width > mWidth Then mWidth = Me.Width
            End Select
    
            .Size mWidth, mHeight
            MoveWindow ToolBarHandle, 0, 0, .ScaleWidth, .ScaleHeight, 1
        End With
    
        InProc = False
    End Sub
    But as I said, I did do the test ONLY on XP, so ....

    Otherwise, nice work, I hope I can continue to make my contribution to the building.


    kind regards

  40. #560
    Member lrd_VB6's Avatar
    Join Date
    Jul 2014
    Location
    FRANCE
    Posts
    36

    Re: CommonControls (Replacement of the MS common controls)

    Oups
    Last edited by lrd_VB6; Nov 15th, 2014 at 06:19 AM.

Page 14 of 105 FirstFirst ... 4111213141516172464 ... LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width