Tặng Hàm MsgBox Việt hóa font Unicode tuyệt đẹp! (Phần 2 - 32bit/64bit)

Liên hệ QC

Hoàng Trọng Nghĩa

Chuyên gia GPE
Thành viên BQT
Moderator
Tham gia
17/8/08
Bài viết
8,655
Được thích
16,711
Giới tính
Nam
Nhu cầu Việt hóa cao cho các thông điệp bằng MsgBox nên tôi lại tiếp tục với phiên bản 2 có thể chạy trên Win32bit và Win64bit.

Một số hình ảnh sinh động của Phiên bản này:

Msg1.jpg

Msg2.jpg

Msg3.jpg

Msg4.jpg

Hàm MyUniMsgBox:

Mã:
Function MyUniMsgBox(ByVal msgTitle As String, _
                     Optional msgText As String, _
                     Optional msgButtonType As MsoAlertButtonType, _
                     Optional msgIconType As MsoAlertIconType, _
                     Optional msgDefaultType As MsoAlertDefaultType) As VbMsgBoxResult
    ''---------------------------------------------------------------------------------------------------
    ''Cau truc: MyUniMsgBox TieuDe (bat buoc), [NoiDung], [KieuNutLenh], [KieuIcon], [KieuNutLenhMacDinh]
    ''---------------------------------------------------------------------------------------------------
    hHook = SetWindowsHookEx(WH_CBT, AddressOf MsgBoxHookProc, 0, GetCurrentThreadId)
    On Error Resume Next
    MyUniMsgBox = Assistant.DoAlert(msgTitle, _
                                    msgText, _
                                    msgButtonType, _
                                    msgIconType, _
                                    msgDefaultType, _
                                    msoAlertCancelDefault, _
                                    False)
    If Err.Number Then
    Err.Clear
    MyUniMsgBox = Assistant.DoAlert(msgTitle, _
                                    msgText, _
                                    msgButtonType, _
                                    msgIconType, _
                                    msoAlertDefaultFirst, _
                                    msoAlertCancelDefault, _
                                    False)
    End If
End Function
[CODE]
 

File đính kèm

  • MyUniMsgBox_V2.xls
    60.5 KB · Đọc: 270
Lần chỉnh sửa cuối:
Msgbox này của nghĩa rất hay nếu Bạn nào biết ứng dụng nó thì tuyệt vời

Mình phát hiện thấy có thể thêm Ico của win cho Msgbox các kiểu từ bài này Nếu Bạn nào chưa rành chế code của nghĩa thì có thể tham khảo thêm (Vì trong File Bài #1 Nghĩa làm dạng Tổng Quát sẽ hơi khó cho Bạn mới làm quen với VBA Ứng dụng nó)
Bài #14
http://www.giaiphapexcel.com/forum/...-Tiêu-Đề-Msgbox-Là-Chữ-Đậm-Hoặc-Nghiêng/page2
 
Upvote 0
thầy Nghĩa cho em hỏi cách xử lý nút lệnh trong code cả thầy được không thầy
Mã:
Sub TaoMoixx()
Dim TieuDe, NoiDung As String
    TieuDe = "THÔNG BÁO"
    NoiDung = "Ba5n co1 cha81c ta5o Ho62 so7 mo71i"
a= MyUniMsgBox TieuDe, NoiDung, _
                            msoAlertButtonOKCancel, _
                            4, _
                            msoAlertDefaultFirst
If a = 1 Then MsgBox "ban nhan yes" Else MsgBox "ban nhan no"
Exit Sub
em làm như vậy thì nó báo lỗi
 
Upvote 0
thầy Nghĩa cho em hỏi cách xử lý nút lệnh trong code cả thầy được không thầy
Mã:
Sub TaoMoixx()
Dim TieuDe, NoiDung As String
    TieuDe = "THÔNG BÁO"
    NoiDung = "Ba5n co1 cha81c ta5o Ho62 so7 mo71i"
a= MyUniMsgBox TieuDe, NoiDung, _
                            msoAlertButtonOKCancel, _
                            4, _
                            msoAlertDefaultFirst
If a = 1 Then MsgBox "ban nhan yes" Else MsgBox "ban nhan no"
Exit Sub
em làm như vậy thì nó báo lỗi

Hình như bạn còn thiếu hàm Convert mã Unicode cho NoiDung thì phải! Đồng thời bạn chưa khai báo a là dạng gì.
 
Upvote 0
Hình như bạn còn thiếu hàm Convert mã Unicode cho NoiDung thì phải! Đồng thời bạn chưa khai báo a là dạng gì.
Hình như bạn còn thiếu hàm Convert mã Unicode cho NoiDung thì phải! Đồng thời bạn chưa khai báo a là dạng gì.
cái phần nội dung không quan trọng thầy ạ
nó báo lỗi ngay TieuDe ấy thầyView attachment 149763
code nằm trong Modelu2 thầy ạ
trong khi đó code này thì chạy được
Mã:
Private Sub Form_Load()
   Dim testmsg As    Integer 
    testmsg = MsgBox("Test thu 1 vi du", [COLOR=Red][B]1[/B][/COLOR][B], "Vi du") 
    If [COLOR=Red][B]testmsg = 1[/B][/COLOR][B] Then   
     msgbox("Ban vua nhan OK" )
    Else 
       msgbox("Ban vua nhan Cancel" )
    End If
End Sub[/B][/B]
 

File đính kèm

  • HosoKCS.xlam
    101.1 KB · Đọc: 25
Upvote 0
thầy Nghĩa cho em hỏi cách xử lý nút lệnh trong code cả thầy được không thầy
Mã:
[COLOR=#ff0000]Sub [/COLOR]TaoMoixx()
Dim TieuDe, NoiDung As String
    TieuDe = "THÔNG BÁO"
    NoiDung = "Ba5n co1 cha81c ta5o Ho62 so7 mo71i"
a= MyUniMsgBox TieuDe, NoiDung, _
                            msoAlertButtonOKCancel, _
                            4, _
                            msoAlertDefaultFirst
If a = 1 Then MsgBox "ban nhan yes" Else MsgBox "ban nhan no"
[COLOR=#ff0000]Exit Sub[/COLOR]
em làm như vậy thì nó báo lỗi
Code của bạn nó sai cơ bản 2 chỗ:

1) Trên là SUB thì dưới phải là END SUB chứ không phải EXIT SUB

2) Với hàm, nếu không có các thủ tục như CALL như Msg = MyUniMsgBox thì chúng không có dấu ngoặc (), còn như bạn, với a= MyUniMsgBox thì phải chứa trong ngoặc các đối số còn lại a = MyUniMsgBox(a,b,c,d)

Và lưu ý thêm về các Constant của MsgBox trả về đó là:

vbOK = 1

vbCancel = 2

vbAbort = 3

vbRetry = 4

vbIgnore = 5

vbYes = 6

vbNo = 7

Vậy cho nên thủ tục của bạn cần sửa lại như sau:

Mã:
Sub TaoMoixx()
    Dim Msg As Long
    Dim TieuDe As String, NoiDung As String
        TieuDe = "THÔNG BÁO"
        NoiDung = "Ba5n co1 cha81c ta5o Ho62 so7 mo71i"
        Msg = MyUniMsgBox[COLOR=#ff0000]([/COLOR]TieuDe, NoiDung, msoAlertButtonOKCancel, 4, msoAlertDefaultFirst[COLOR=#ff0000])[/COLOR]
    If Msg = 1 Then MsgBox "ban nhan OK" Else MsgBox "ban nhan CANCEL"
End Sub
 
Upvote 0
Code của bạn nó sai cơ bản 2 chỗ:

1) Trên là SUB thì dưới phải là END SUB chứ không phải EXIT SUB

2) Với hàm, nếu không có các thủ tục như CALL như Msg = MyUniMsgBox thì chúng không có dấu ngoặc (), còn như bạn, với a= MyUniMsgBox thì phải chứa trong ngoặc các đối số còn lại a = MyUniMsgBox(a,b,c,d)

Và lưu ý thêm về các Constant của MsgBox trả về đó là:

vbOK = 1

vbCancel = 2

vbAbort = 3

vbRetry = 4

vbIgnore = 5

vbYes = 6

vbNo = 7

Vậy cho nên thủ tục của bạn cần sửa lại như sau:

Mã:
Sub TaoMoixx()
    Dim Msg As Long
    Dim TieuDe As String, NoiDung As String
        TieuDe = "THÔNG BÁO"
        NoiDung = "Ba5n co1 cha81c ta5o Ho62 so7 mo71i"
        Msg = MyUniMsgBox[COLOR=#ff0000]([/COLOR]TieuDe, NoiDung, msoAlertButtonOKCancel, 4, msoAlertDefaultFirst[COLOR=#ff0000])[/COLOR]
    If Msg = 1 Then MsgBox "ban nhan OK" Else MsgBox "ban nhan CANCEL"
End Sub
Cảm ơn thầy nhiều. code đó em cắt trong 1 khúc code của em viết nên ở khúc giữa nó mới có exit sub như thế. xem code của thầy thì mới biết thì ra là phải thêm 2 dấu ngoặc vô nữa --=0
em nhớ hình như là msoAlertButtonOKCancel mình thay bằng số tương ứng được đúng không thầy.
với chỗ này
msoAlertDefaultFirst có thể thay thế 1 số nào đó tương ứng được không, chứ mỗi lần thay đổi lại xem lại để copy.
do chả qua trường lớp nào nên chả nhớ gì nhiều toàn đi copy đi copy lại ,,,,,,,,,,,
 
Lần chỉnh sửa cuối:
Upvote 0
Mã:
Option Explicit
'------------------------------------------------------------------------
Private hHook As Long
'******************************************************************************************************************************
#If VBA7 Then  'Office 64-bit
    Private Declare PtrSafe Function GetCurrentThreadId Lib "kernel32" () As Long
    Private Declare PtrSafe Function SetDlgItemText Lib "user32" Alias "SetDlgItemTextW" (ByVal hDlg As LongPtr, ByVal nIDDlgItem As LongPtr, ByVal lpString As LongPtr) As Long
    Private Declare PtrSafe Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As LongPtr, ByVal lpfn As LongPtr, ByVal hmod As LongPtr, ByVal dwThreadId As LongPtr) As Long
    Private Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As LongPtr) As Long
#Else ' Office 32-bit
    Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
    Private Declare Function SetDlgItemText Lib "user32" Alias "SetDlgItemTextW" (ByVal hDlg As Long, ByVal nIDDlgItem As Long, ByVal lpString As Long) As Long
    Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
    Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
#End If
'******************************************************************************************************************************
Private Const WH_CBT = 5
Private Const HCBT_ACTIVATE = 5
''------------------------------------------------------------------------
Private Const IdOK = 1
Private Const IdCancel = 2
Private Const IdAbort = 3
Private Const IdRetry = 4
Private Const IdIgnore = 5
Private Const IdYes = 6
Private Const IdNo = 7
Private Const IdYesAll = 8
'------------------------------------------------------------------------
Private Const strAllButton As String = "63006800e2004103700020006e006800e20023036e00,6800e71e790020006200cf1e,6800e71e790020006e00670061006e006700,74006800ed1e20006c00a11e6900,4200cf1e2000710075006100,4300f300,6b006800f4006e006700,4300f30020007400a51e740020006300a31e"
'******************************************************************************************************************************

Private Function MsgBoxHookProc(ByVal lMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Dim I As Long
    Dim strButton() As String
    If lMsg = HCBT_ACTIVATE Then
        strButton = Split(strAllButton, ",")
        For I = IdOK To IdYesAll
          SetDlgItemText wParam, I, StrPtr(HexASCIIToString(strButton(I - 1)))
        Next I
        UnhookWindowsHookEx hHook
    End If
    MsgBoxHookProc = False
End Function
'******************************************************************************************************************************

Function MyUniMsgBox(ByVal msgTitle As String, _
                     Optional msgText As String, _
                     Optional msgButtonType As MsoAlertButtonType, _
                     Optional msgIconType As MsoAlertIconType, _
                     Optional msgDefaultType As MsoAlertDefaultType) As VbMsgBoxResult
    ''---------------------------------------------------------------------------------------------------
    ''Cau truc: MyUniMsgBox TieuDe (bat buoc), [NoiDung], [KieuNutLenh], [KieuIcon], [KieuNutLenhMacDinh]
    ''---------------------------------------------------------------------------------------------------
    hHook = SetWindowsHookEx(WH_CBT, AddressOf MsgBoxHookProc, 0, GetCurrentThreadId)
    On Error Resume Next
    MyUniMsgBox = Assistant.DoAlert(msgTitle, _
                                    msgText, _
                                    msgButtonType, _
                                    msgIconType, _
                                    msgDefaultType, _
                                    msoAlertCancelDefault, _
                                    False)
    If Err.Number Then
        Err.Clear
        MyUniMsgBox = Assistant.DoAlert(msgTitle, _
                                        msgText, _
                                        msgButtonType, _
                                        msgIconType, _
                                        msoAlertDefaultFirst, _
                                        msoAlertCancelDefault, _
                                        False)
    End If
End Function
'******************************************************************************************************************************
Private Function HexASCIIToString(ByVal strASCII As String) As String
  Dim I         As Long
  Dim K         As Long
  Dim bytArr()  As Byte
  
  I = Len(strASCII) \ 2
  If I > 0 Then
    ReDim bytArr(0 To I - 1)
    For I = 1 To Len(strASCII) - 1 Step 2
      bytArr(K) = CLng("&H" & Mid$(strASCII, I, 2))
      K = K + 1
    Next I
  End If
  HexASCIIToString = bytArr()
End Function
 
Upvote 0
Mã:
Option Explicit

'------------------------------------------------------------------------
Private Const strAllButton As String = "63006800e2004103700020006e006800e20023036e00,6800e71e790020006200cf1e,6800e71e790020006e00670061006e006700,74006800ed1e20006c00a11e6900,4200cf1e2000710075006100,4300f300,6b006800f4006e006700,4300f30020007400a51e740020006300a31e"
'******************************************************************************************************************************
Private Function MsgBoxHookProc(ByVal lMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Dim I As Long
    Dim strButton() As String
    If lMsg = HCBT_ACTIVATE Then
        strButton = Split(strAllButton, ",")
        For I = IdOK To IdYesAll
          SetDlgItemText wParam, I, StrPtr(HexASCIIToString(strButton(I - 1)))
        Next I
        UnhookWindowsHookEx hHook
    End If
    MsgBoxHookProc = False
End Function

End Function
'******************************************************************************************************************************
Private Function HexASCIIToString(ByVal strASCII As String) As String
  Dim I         As Long
  Dim K         As Long
  Dim bytArr()  As Byte
  
  I = Len(strASCII) \ 2
  If I > 0 Then
    ReDim bytArr(0 To I - 1)
    For I = 1 To Len(strASCII) - 1 Step 2
      bytArr(K) = CLng("&H" & Mid$(strASCII, I, 2))
      K = K + 1
    Next I
  End If
  HexASCIIToString = bytArr()
End Function
Thanks for your improving my code.

But what special thing different between my code and your improving code?

I think them more procedure than mine.

And the most important thing is someone can change the a button in another meaning, not translate it.

For example:

The Button OK may translate to "Đồng ý", "Chấp nhận", "Phải", "Được".

But sometimes I want to change it by "Tuyệt" (great), if I use your code, how can I do it?
 
Lần chỉnh sửa cuối:
Upvote 0
But what special thing different between my code and your improving code?
你的原代码中,如果在不支持越南语中的系统中运行,则按钮显示的文字会显示成乱码。修改后的代码则会正常显示出越南语。这是因为VBA代码总是被处理成ASCII编码保存在Excel文件中。
And the most important thing is someone can change the a button in another meaning, not translate it.

For example:

The Button OK may translate to "Đồng ý", "Chấp nhận", "Phải", "Được".

But sometimes I want to change it by "Tuyệt" (great), if I use your code, how can I do it?
如果需要改变这些文字,只需要事先使用下面的代码计算出文字的Hex值字符串,然后再使用HexASCIIToString还原即可。
Mã:
Private Function StringToASCII(ByVal strUnicode As String) As String
  Dim I         As Long
  Dim K         As Long
  Dim bytArr()  As Byte
  
  If Len(strUnicode) Then
    bytArr() = strUnicode
    For I = 0 To UBound(bytArr)
      StringToASCII = StringToASCII & IIf(bytArr(I) > &HF, vbNullString, "0") & Hex$(bytArr(I))
    Next I
  End If
End Function
Debug.Print StringToASCII("This a test")
 
Upvote 0
Đề bài thì "nhu cầu Việt hoá"

Thân bài thì thấy nói chuyện toàn tiếng tây tiếng tàu?

Tuyệt đẹp thì có đẹp thiệt. Nhưng thực tế, hiểu mục đích mấy người này chết liền.
 
Upvote 0
Kỹ thuật mà bạn 南宫飘雪 đưa ra là chuyển đổi chuỗi về giá trị Hexa, đưa chuỗi giá trị đó và mảng rồi lại chuyển Hexa về mảng giá trị là Byte (longe). Bản chất chuỗi ký tự là mảng ký tự (một chiều), mỗi phần tử mảng giữ ký tự được mã hóa dạng BYTE. Bài cuối cùng 南宫飘雪 đưa ra hàm chuyển đổi ngược là StringToHex để chúng ta biết mấy cái chuỗi loằng ngoằng từ đâu mà có. Tóm lại , đồng chí 南宫飘雪 là cao thủ lập trình VB6.
南宫飘雪, you are professional programming in VB language!
 
Upvote 0
Kỹ thuật mà bạn 南宫飘雪 đưa ra là chuyển đổi chuỗi về giá trị Hexa, đưa chuỗi giá trị đó và mảng rồi lại chuyển Hexa về mảng giá trị là Byte (longe). Bản chất chuỗi ký tự là mảng ký tự (một chiều), mỗi phần tử mảng giữ ký tự được mã hóa dạng BYTE. Bài cuối cùng 南宫飘雪 đưa ra hàm chuyển đổi ngược là StringToHex để chúng ta biết mấy cái chuỗi loằng ngoằng từ đâu mà có. Tóm lại , đồng chí 南宫飘雪 là cao thủ lập trình VB6.
南宫飘雪, you are professional programming in VB language!
Đôi lúc em thấy mã hóa kiểu này với máy em hình như dấu tiếng Việt đặt vẫn chưa chuẩn vị trí anh à. Nó na ná giống font Unicode Tổ hợp được vẽ trên Form vậy, có khi dấu sắc/dấu huyền... nó chạy tuốt luốt ra sau! (Nhưng có lẽ nó sẽ đúng với CustomUI cho Ribbon).
 
Upvote 0
Đôi lúc em thấy mã hóa kiểu này với máy em hình như dấu tiếng Việt đặt vẫn chưa chuẩn vị trí anh à. Nó na ná giống font Unicode Tổ hợp được vẽ trên Form vậy, có khi dấu sắc/dấu huyền... nó chạy tuốt luốt ra sau! (Nhưng có lẽ nó sẽ đúng với CustomUI cho Ribbon).

Cấu trúc chuyển đổi giá trị từ Hexa->BYTE (array)->String là chuẩn. Còn vấn đề chuỗi hiển thị như thế nào lại dó cách chuyển đổi:
AnsiString to UTF8
AnsiString to UTF16
AnsiString to UNICODE
ANSI là chuẩn của VBA/VB6
 
Lần chỉnh sửa cuối:
Upvote 0
Mấy bác này tài thật, mình chẳng hiểu tí gì về ngôn ngữ "tàu lao" đó, vậy mà vẫn trả lời như tiếng Việt vậy.
 
Upvote 0
Gú gồ dịch tiếng Anh không chuẩn lắm. Tiếng Tàu lại càng trât vuột.
 
Upvote 0
Gú gồ dịch tiếng Anh không chuẩn lắm. Tiếng Tàu lại càng trât vuột.

Thật ra công cụ google dịch khá hay, nếu ta biết một chút ngữ pháp ta điều chỉnh sự "dịch chay" của nó thì ngon lành, nhưng cũng phải lường được tình huống "dịch bồi" của anh google nữa!
 
Upvote 0
Cái khó ở chỗ "biết một chút ngữ pháp"
Thỉnh thoảng tôi vẫn thấy người ta hiểu sai vì gú gồ chọn ngữ pháp và lường ngữ cảnh không đúng khiến kết quả có nghĩa khác.
Cái tôi nói áp dụng cho cả 2 chiều, Việt-Anh và Anh-Việt

Nhất là khi bạn chạm vào thành ngữ. Mà tiếng Anh là tiếng nhiều thành ngữ nhất thế giới.
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn Hoàng Trọng Nghĩa cho mình hỏi, mình thử đổi nội dung của msgbox và chạy thử thì nó ra thế này. Mình ko biết làm thế nào cho nó thu hẹp cái msgbox lại và bôi đậm ở cái TieuDeCap2 như bạn làm.
Mong bạn giúp đỡ!
Sub dlt()
Dim i As Integer
Dim a As Integer
Dim Xoa As Integer
Dim TieuDe As String, TieuDeCap2 As String, NoiDung As String
TieuDeCap2 = Sheet1.Range("K1") & vbLf
TieuDe = TieuDeCap2
NoiDung = Sheet1.Range("K2")
Xoa = MyUniMsgBox(TieuDe, NoiDung, msoAlertButtonOKCancel, 2, msoAlertDefaultFirst)
If Xoa = 1 Then
For i = 9 To 100
If Cells(i, 5).Value = "Done" Then
Rows(i).EntireRow.Delete
End If
Next i
If Xoa = 2 Then
End If
End If
End Sub
Capture.jpg
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Web KT
Back
Top Bottom