Chỉnh Font của menu Form đọc được.

Liên hệ QC

quykh

Chim non
Tham gia
7/9/11
Bài viết
381
Được thích
46
Giới tính
Nữ
Nghề nghiệp
Công Nhân
Em có file Excel sử dụng Menu Form của anh Tuân, dùng ở nhà thì không sao, nhưng đem lên công ty dùng máy công ty, thì lỗi font không đọc được. Do máy công ty có xài phần mềm Foxpro, và anh viết phần mềm Foxpro đó có chỉnh font của Window color, cụ thể là chỉnh font của Menu, Active Tille Bar, Inactive Tille Bar là MS Sans Serif.
Nên Font của Menu Excel hiện ra như vầy:
220850
Mong các Anh Chị giúp em đoạn code cho menu form Excel hiện cho đọc được ạ.
 
Em có file Excel sử dụng Menu Form của anh Tuân, dùng ở nhà thì không sao, nhưng đem lên công ty dùng máy công ty, thì lỗi font không đọc được. Do máy công ty có xài phần mềm Foxpro, và anh viết phần mềm Foxpro đó có chỉnh font của Window color, cụ thể là chỉnh font của Menu, Active Tille Bar, Inactive Tille Bar là MS Sans Serif.
Nên Font của Menu Excel hiện ra như vầy:
View attachment 220850
Mong các Anh Chị giúp em đoạn code cho menu form Excel hiện cho đọc được ạ.
Thì đồ chơi không hệ thống, khi người ta chỉnh sai khác là sai ngay
Không nên dùng các đồ chơi màu sắc vậy
 
Upvote 0
Vì Foxpro không hỗ trợ Unicode nên phải chỉnh Font hệ thống.
 
Upvote 0
Giờ vẫn còn phần mềm viết = Fox hả bạn ?
Nhớ là có nhiều cách, không cần phải dùng tới API cho lòng vòng, rắc rối, mà ngồi nhớ hoài không ra. Già, mau quên rồi.
Thôi trước mắt bạn dùng code VBA và API thử đi. Tham khảo tại link này, thấy code đúng hướng rồi đó.
 
Lần chỉnh sửa cuối:
Upvote 0
Em không biết cái nenu form của em có phải là Msgbox không nữa, File gốc của anh Nguyễn Duy Tuân ở đây Ạ:
Cái này chắc phải nhờ anh Tuân .
 
Upvote 0
Cái này chắc phải nhờ anh Tuân .
Trong bài #4 bạn có giải pháp rồi còn gì. Copy code cho vào 1 module. Trong UserForm_Initialize gọi SetSysFont "Times New Roman" để thay phông chữ trong thời gian Form hiển thị. Trong UserForm_Terminate thì gọi RestoreSysFont để trả lại thiết lập cho thằng Fox.
Nhớ là 2 hàm trên sửa thành Public vì để ở module khác.

Còn về Tuân thì có lẽ không có thời gian cho bạn đâu. Vì sao?

Sửa menu của Tuân không phải dễ và cũng không phải là mất ít thời gian. Nhiều cái có thể dính dáng với nhau và có thể sửa chỗ này lại phải sửa cả chỗ khác. Dò rất mất thời gian.

Cái OwnerDraw của Tuân chỉ tác dụng cho các mục menu con (ở các danh sách thả xuống) chứ không cho các mục menu chính trên thanh menu.

Có 2 chế độ vẽ menu: Để Windows tự vẽ hoặc tự mình vẽ:

- khi tạo menu mà OwnerDraw = FALSE thì Windows tự "vẽ" menu bằng phông chữ được thiết lập trong system. Nếu phông chữ không phục vụ unicode thì sẽ có "đầu trâu mặt ngựa".

- khi tạo menu mà OwnerDraw = TRUE thì khi cần "vẽ" mỗi mục menu Windows sẽ gửi 2 thông điệp tới cửa sổ:

a. WM_MEASUREITEM
Kèm theo thông điệp đó là lParam = Pointer tới cấu trúc mi = MEASUREITEMSTRUCT.
Nhiệm vụ của code là phải tính ra chiều dài và chiều cao cần thiết của mục menu, vd. mục menu = "Ngày mai mưa" thì rõ ràng cần tính ra độ dài ngắn hơn so với trường hợp mục menu = "Ngày mai em đi. Biển nhớ tên em gọi về". Tính xong rồi thì phải trả cho Windows 2 giá trị dài cao đó trong 2 trường mi.itemWidth và mi.itemHeight.

b. WM_DRAWITEM. Được gửi sau thông điệp WM_MEASUREITEM
Kèm theo thông điệp đó là lParam = Pointer tới cấu trúc dis = DRAWITEMSTRUCT
Windows sẽ cung cấp trong dis nhiều thứ, trong đó dis.rcItem là hình chữ nhật có dài và cao như code đã trả về ở điểm a. Trong dis.hDC là device context mà trong đó code sẽ phải tự "vẽ" mục menu. Nếu không vẽ gì thì mục menu sẽ trống. Còn nếu tự vẽ thì có muôn vàn khả năng. Có thể "vẽ" text (DrawTextW), bitmap (BitBlt, StretchBlt), dùng phông chữ tự chọn, mầu chữ tự chọn (không chỉ là đen), có thể italic, đổ mầu nền, vân vân và mây mây. Mục đích dùng OwnerDraw = TRUE là để có thể tha hồ tự mình vẽ. Mà nếu OwnerDraw = TRUE thì bắt buộc phải tự vẽ. Không vẽ gì thì menu sẽ trống.

Tôi nghĩ không ai dò và sửa code của Tuân cho bạn đâu. Trừ phi đủ sức và thừa nhiều thời gian. Mà cả Tuân chắc là thời gian sửa code cho bạn thì có thể làm việc của mình để thêm váy cho vợ, thêm nhà hàng, du lịch cho vợ con. Của biếu thì có lẽ chỉ làm đến thế thôi. Ai rỗi hơn mà làm theo từng yêu cầu đang và sẽ có.
 
Upvote 0
Em đã làm menu hiện chữ đọc được, nhưng caption của form lại không đọc được. Mong Thầy @batman1 xem giúp.
220905
 
Upvote 0
Em đã làm menu hiện chữ đọc được, nhưng caption của form lại không đọc được. Mong Thầy @batman1 xem giúp.
View attachment 220905
Thực ra người ta làm chưa chuẩn nên với thay đổi phông chữ của thanh tiêu đề có nảy sinh vấn đề.
Sau khi thay đổi những cái dùng chung trong system thì thông báo cho bàn dân thiên hạ biết sự thay đổi.

Mã:
SendMessage HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0

1. Code trong Form
Mã:
Private Sub UserForm_Initialize()
    SetSysFont "Times New Roman"
    setTitle Me.caption, TIÊU ĐỀ TIẾNG VIỆT
'    ...
End Sub

Private Sub UserForm_Terminate()
    RestoreSysFont
'    ...
End Sub

2. Code module. Tôi chỉ thay đổi phông chữ cho thanh tiêu đề và menu. Nếu có nhu cầu thì tự thêm.
Mã:
Private Const SPI_GETNONCLIENTMETRICS = 41
Private Const SPI_SETNONCLIENTMETRICS = 42
Private Const WM_SETTEXT = &HC
Private Const WM_SETTINGCHANGE As Long = &H1A
Private Const HWND_BROADCAST As Long = &HFFFF&

Private Type LOGFONT
        lfHeight As Long
        lfWidth As Long
        lfEscapement As Long
        lfOrientation As Long
        lfWeight As Long
        lfItalic As Byte
        lfUnderline As Byte
        lfStrikeOut As Byte
        lfCharSet As Byte
        lfOutPrecision As Byte
        lfClipPrecision As Byte
        lfQuality As Byte
        lfPitchAndFamily As Byte
        lfFaceName As String * 32
End Type

Private Type NONCLIENTMETRICS
    cbSize As Long
    iBorderWidth As Long
    iScrollWidth As Long
    iScrollHeight As Long
    iCaptionWidth As Long
    iCaptionHeight As Long
    lfCaptionFont As LOGFONT
    iSMCaptionWidth As Long
    iSMCaptionHeight As Long
    lfSMCaptionFont As LOGFONT
    iMenuWidth As Long
    iMenuHeight As Long
    lfMenuFont As LOGFONT
    lfStatusFont As LOGFONT
    lfMessageFont As LOGFONT
End Type

#If VBA7 Then
    Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
    Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
    Private Declare PtrSafe Function DefWindowProcW Lib "user32" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
    Private Declare PtrSafe Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" (ByVal uAction As Long, ByVal uParam As Long, ByRef lpvParam As Any, ByVal fuWinIni As Long) As Long
#Else
    Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    Private Declare Function DefWindowProcW Lib "user32" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function SystemParametersInfo Lib "user32.dll" Alias "SystemParametersInfoA" (ByVal uAction As Long, ByVal uParam As Long, ByRef lpvParam As Any, ByVal fuWinIni As Long) As Long
#End If

Dim fontmenu As String, fontcaption As String, ncm As NONCLIENTMETRICS

Public Sub SetSysFont(fontname As String)
    ncm.cbSize = Len(ncm)
    SystemParametersInfo SPI_GETNONCLIENTMETRICS, Len(ncm), ncm, 0
   
    fontmenu = ncm.lfMenuFont.lfFaceName
    fontcaption = ncm.lfCaptionFont.lfFaceName
    ncm.lfMenuFont.lfFaceName = fontname & vbNullChar
    ncm.lfCaptionFont.lfFaceName = fontname & vbNullChar
    SystemParametersInfo SPI_SETNONCLIENTMETRICS, Len(ncm), ncm, 0
   
    SendMessage HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0
End Sub

Public Sub RestoreSysFont()
    ncm.lfMenuFont.lfFaceName = fontmenu
    ncm.lfCaptionFont.lfFaceName = fontcaption

    SystemParametersInfo SPI_SETNONCLIENTMETRICS, Len(ncm), ncm, 0
   
    SendMessage HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0
End Sub

Public Sub setTitle(ByVal ufCaption As String, ByVal windowText As String)
#If VBA7 Then
    Dim hwnd As LongPtr
#Else
    Dim hwnd As Long
#End If
    hwnd = FindWindow("ThunderDFrame", ufCaption)
    If hwnd > 0 Then DefWindowProcW hwnd, WM_SETTEXT, 0, StrPtr(windowText)
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Cám ơn Thầy @batman1 nhiếu!!!
 
Upvote 0
Hoặc bỏ SendMessage. Lúc này cần khai báo
Mã:
Private Const SPIF_SENDCHANGE As Long = &H2

Sau đó sửa 2 chỗ thành
Mã:
SystemParametersInfo SPI_SETNONCLIENTMETRICS, Len(ncm), ncm, SPIF_SENDCHANGE
 
Upvote 0
Mã:
Private Sub UserForm_Initialize()
    SetSysFont "Times New Roman"
    setTitle Me.caption, TIÊU ĐỀ TIẾNG VIỆT ' chổ này làm sao Thầy???
'    ...
End Sub

Private Sub UserForm_Terminate()
    RestoreSysFont
'    ...
End Sub
chổ "TIÊU ĐỀ TIẾNG VIỆT" thì làm sao em không biết Thầy @batman1 ơi??
 
Upvote 0
Mã:
Private Sub UserForm_Initialize()
    SetSysFont "Times New Roman"
    setTitle Me.caption, TIÊU ĐỀ TIẾNG VIỆT ' chổ này làm sao Thầy???
'    ...
End Sub

Private Sub UserForm_Terminate()
    RestoreSysFont
'    ...
End Sub
chổ "TIÊU ĐỀ TIẾNG VIỆT" thì làm sao em không biết Thầy @batman1 ơi??
Là nhập chuỗi của mình. Vd. "KHU NGUYÊN VẬT LIỆU". Chịu khó suy nghĩ chút đi.

SetTitle, TIÊU ĐỀ không nói cái gì, gợi ý cái gì? Nhất là khi vấn đề đang xét là "nhập tiêu đề tiếng Việt"
 
Upvote 0
Sao em làm nó ra như vầy ạ:
220921
cái Caption vẫn chưa hiện đúng ạ.
Không biết em có làm sai chổ nào, mong Thầy @batman1 chỉ rỏ cách làm ạ.
 
Upvote 0
1. Đã hỏi trên GPE thì giải quyết trên GPE chứ không phải giữa chừng lại gửi vào hộp thoại. Vì như thế chủ đề trên GPE sẽ treo lơ lửng không có kết.

2. Nên nhớ GPE không là diễn đàn dành cho những người đam mê chụp ảnh. Có những cái không nhìn được trên ảnh, không đoán được từ "nước bọt".

Gửi tập tin thì lòi ngay ra cái sai. Hãy nhìn kỹ ảnh dưới. Rõ ràng bạn cung cấp chuỗi "KHO NGUYÊN PH? LI?U" mà còn kêu.

Lúc này thì còn đâu và Ệ mà chỉ có ? được cung cấp cho setTitle.

123.JPG

Hãy sửa thành
Mã:
setTitle Me.Caption, "KHO NGUY" & ChrW(202) & "N PH" & ChrW(7908) & " LI" & ChrW(7878) & "U"

thì sẽ nhìn thấy như hình dưới.

456.JPG

Lưu ý:
chuỗi tiếng Việt không thể nhập trực tiếp trong VBE. Hoặc làm như trên hoặc lưu chuỗi trên sheet rồi đọc vào. vd. lưu tại Sheet1!A1 thì
Mã:
setTitle Me.Caption, Sheet1.Range("A1").Value
 
Upvote 0
Dạ em cám ơn Thầy @batman1 ạ!!!!!
 
Upvote 0
Sao em làm như Thầy chỉ mà nó ra như vầy:
220956
chữ "NGUYÊN" bị lỗi.
code em làm giống thầy:
Mã:
Private Sub UserForm_Initialize()
    'Create menu
    hForm = FindWindow("ThunderDFrame", Caption)
    Set MyUMUMenu = New UMUMenu
    On Error Resume Next
Application.EnableCancelKey = xlDisabled
    HideCloseBox Me
DoFormInit Me, hwnd, wStyle, OldWidth, OldHeight, OldInsideWidth, OldInsideHeight, lastScaleX, lastScaleY
    SetSysFont "Times New Roman"
    setTitle Me.Caption, "KHO NGUY" & ChrW(202) & "N PH" & ChrW(7908) & " LI" & ChrW(7878) & "U"

    MyUMUMenu.DrawStyle = dsOwnerdraw
    With MyUMUMenu
        .BkColor = RGB(165, 212, 87)  ' 255,236,139
        .SelBkColor = RGB(100, 142, 130)
        .TextColor = vbBlack
        .SelTextColor = vbWhite
    End With
    
    hForm = GetHandle(Me)
    hMenu = MyUMUMenu.Create(Application, hForm, cMENUTABLE)
Mong Thầy xem giúp em.
 
Upvote 0
Em bỏ dòng HideCloseBox Me thì vẫn bị, bò DoFormInit thì bị lỗi vàng
Mã:
scaleX = form.InsideWidth / OldInsideWidth

(DoFormInit để bung Form toàn màn hình)
 
Upvote 0
Em bỏ dòng HideCloseBox Me thì vẫn bị,
Ừ đúng. Thằng DefWindowProcW nhập tiếng Việt lên thanh tiêu đề chỉ khi trong lần mở Excel hiện hành không có code thay đổi phông chữ của system. Nếu trong lần mở Excel hiện hành có code thay đổi phông chữ của system thì nó lại không nhập tiếng Việt. Có cảm giác là khi mở Excel thì nó nhớ thiết lập rồi không đếm xỉa tới sự thay đổi nữa. Kiểu như mù và điếc vậy.
Có lẽ chỉ còn cách trước khi mở Excel thì thay đổi phông chữ của system rồi sau khi tắt Excel lại trả về như trước.
Nhưng cũng lạ là với phông chữ của menu chính thì lại bình thường. Có lẽ do thằng DefWindowProcW nhạy cảm với sự thay đổi chăng. Tôi cũng chịu không hiểu tại sao.
 
Upvote 0
Web KT
Back
Top Bottom