Xin giải thích và hướng khắc phục khi mở Form con trỏ không thể SetFocus.

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,662
Được thích
16,720
Giới tính
Nam
Xin vui lòng hướng dẫn và giúp đỡ:
Tại sao khi mở Form (có sử dụng MinMax), con trỏ không thể SetFocus vào combobox hay textbox?
Có khắc phục vấn đề này được không?
Trân trọng cảm ơn!
 

File đính kèm

Initialize Event xảy ra sau khi object được nạp nhưng trước khi object hiển thị do vậy phương thức SetFocus không có tác dụng.

Anh dời SetFocus sang sự kiện Activate là được.

TTP.
 
Upvote 0
Initialize Event xảy ra sau khi object được nạp nhưng trước khi object hiển thị do vậy phương thức SetFocus không có tác dụng.

Anh dời SetFocus sang sự kiện Activate là được.

TTP.

Không được đâu các hạ ơi! Mình đã thử trước rồi mới hỏi đấy!

Private Sub UserForm_Activate()
ComboBox1.SetFocus
End Sub
 
Upvote 0
Xin vui lòng hướng dẫn và giúp đỡ:
Tại sao khi mở Form (có sử dụng MinMax), con trỏ không thể SetFocus vào combobox hay textbox?
Có khắc phục vấn đề này được không?
Trân trọng cảm ơn!
Code dài ngán quá (không dám sửa luôn)
Tôi dùng code của tôi, SetFocus bình thường
PHP:
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
 (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
 (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
PHP:
Private Sub UserForm_Initialize()
  Dim hWnd As Long
  hWnd = FindWindow("ThunderDFrame", Me.Caption)
  SetWindowLong hWnd, -16, &H84CF0080
  'TextBox1.SetFocus
  ComboBox1.SetFocus
End Sub
Xem file
 

File đính kèm

Upvote 0
Em đã thử nhiều cách, Code gốc của nó là:
PHP:
Public Sub MinMax(sCaption As String)
Dim hWndForm As Long
Dim iStyle As Long
If Val(Application.Version) < 9 Then
  hWndForm = FindWindow("ThunderXFrame", sCaption)
Else
  hWndForm = FindWindow("ThunderDFrame", sCaption)
End If
If hWndForm = 0 Then Exit Sub
Select Case iStyle
Case 0
  SetWindowPos hWndForm, HWND_NOTOPMOST, 0, 0, 800, 600, SWP_SHOWWINDOW
Case 1
  SetWindowPos hWndForm, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_HIDEWINDOW
End Select
iStyle = GetWindowLong(hWndForm, GWL_STYLE)
iStyle = iStyle Or WS_MAXIMIZEBOX
iStyle = iStyle Or WS_MINIMIZEBOX
SetWindowLong hWndForm, GWL_STYLE, iStyle
End Sub

Em sửa thành:

PHP:
Public Sub MinMax(sCaption As String)
Dim hWndForm As Long
Dim iStyle As Long
If Val(Application.Version) < 9 Then
  hWndForm = FindWindow("ThunderXFrame", sCaption)
Else
  hWndForm = FindWindow("ThunderDFrame", sCaption)
End If
iStyle = GetWindowLong(hWndForm, GWL_STYLE)
iStyle = iStyle Or WS_MAXIMIZEBOX
iStyle = iStyle Or WS_MINIMIZEBOX
SetWindowLong hWndForm, GWL_STYLE, iStyle
End Sub

Thì nó Setfocus, mà không cần phải Combobox.SetFocus nếu để TabIndex = 0

Nhưng vấn đề đặt ra là khi cái Form từ File của em mở lên nếu bỏ cái Select Case đi thì nó không còn biểu tượng của Form trên Taskbar nữa! Em không muốn mất nó đi!
 
Upvote 0
Em đã thử nhiều cách, Code gốc của nó là:
PHP:
Public Sub MinMax(sCaption As String)
Dim hWndForm As Long
Dim iStyle As Long
If Val(Application.Version) < 9 Then
  hWndForm = FindWindow("ThunderXFrame", sCaption)
Else
  hWndForm = FindWindow("ThunderDFrame", sCaption)
End If
If hWndForm = 0 Then Exit Sub
Select Case iStyle
Case 0
  SetWindowPos hWndForm, HWND_NOTOPMOST, 0, 0, 800, 600, SWP_SHOWWINDOW
Case 1
  SetWindowPos hWndForm, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_HIDEWINDOW
End Select
iStyle = GetWindowLong(hWndForm, GWL_STYLE)
iStyle = iStyle Or WS_MAXIMIZEBOX
iStyle = iStyle Or WS_MINIMIZEBOX
SetWindowLong hWndForm, GWL_STYLE, iStyle
End Sub
Em sửa thành:

PHP:
Public Sub MinMax(sCaption As String)
Dim hWndForm As Long
Dim iStyle As Long
If Val(Application.Version) < 9 Then
  hWndForm = FindWindow("ThunderXFrame", sCaption)
Else
  hWndForm = FindWindow("ThunderDFrame", sCaption)
End If
iStyle = GetWindowLong(hWndForm, GWL_STYLE)
iStyle = iStyle Or WS_MAXIMIZEBOX
iStyle = iStyle Or WS_MINIMIZEBOX
SetWindowLong hWndForm, GWL_STYLE, iStyle
End Sub
Thì nó Setfocus, mà không cần phải Combobox.SetFocus nếu để TabIndex = 0

Nhưng vấn đề đặt ra là khi cái Form từ File của em mở lên nếu bỏ cái Select Case đi thì nó không còn biểu tượng của Form trên Taskbar nữa! Em không muốn mất nó đi!
Thì sửa lại tí:
PHP:
Private Declare Function FindWindow Lib "User32" Alias "FindWindowA" _
 (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SetWindowLong Lib "User32" Alias "SetWindowLongA" _
 (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function SetWindowPos Lib "user32.dll" (ByVal hWnd As Long, _
  ByVal hWndInsertAfter As Long, ByVal x As Long, _
  ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
PHP:
Private Sub UserForm_Initialize()
  Dim hWnd As Long
  hWnd = FindWindow("ThunderDFrame", Me.Caption)
  SetWindowPos hWnd, -2, 0, 0, 800, 600, &H40
  SetWindowLong hWnd, -16, &H84CF0080
  Application.Visible = False
End Sub
PHP:
Private Sub CommandButton1_Click()
  Unload Me
End Sub
PHP:
Private Sub UserForm_Terminate()
  Application.Visible = True
End Sub
Chỉ "ăn chơi" có 1 chút mà phải tốn kém hơi nhiều, quả thật chẳng đáng tí nào
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Thầy ơi, cho em "Được voi đòi 2 bà Trưng" một tí nhé!

1) Có thể nào thay đổi cái biểu tượng Excel trên Taskbar thành một Icon khác được không?

2) Khi nhấp vào biểu tượng đó trên taskbar có thể Min form không? Bởi khi nó đang mở thì click vào biểu tượng trên taskbar nó không Min như những chương trình khác, chỉ chớp chớp tí thôi, nó chỉ được khi đang Min thì click vào nó hiện lại Form.

CÁM ƠN THẦY RẤT NHIỀU!!!
 
Upvote 0
Thầy ơi, cho em "Được voi đòi 2 bà Trưng" một tí nhé!

1) Có thể nào thay đổi cái biểu tượng Excel trên Taskbar thành một Icon khác được không?

2) Khi nhấp vào biểu tượng đó trên taskbar có thể Min form không? Bởi khi nó đang mở thì click vào biểu tượng trên taskbar nó không Min như những chương trình khác, chỉ chớp chớp tí thôi, nó chỉ được khi đang Min thì click vào nó hiện lại Form.

CÁM ƠN THẦY RẤT NHIỀU!!!
1> Vụ thay đổi biểu tượng thì tôi không biết (nếu làm được chắc cũng rất phức tạp) ---> Vậy nếu bạn có như cầu này, thôi thì viết bằng VB đi cho khỏe
2> Tôi vẫn click phải vào biểu tượng của UserForm trên Taskbar và Minimize, Maximize bình thường mà bạn!

untitled.JPG
 
Upvote 0
Trình độ em non kém quá nên không biết dò cách nào để ra cái FormFun này. Trong đó nó có Check lựa chọn Icon luôn, nhưng sử dụng Class.
 

File đính kèm

Upvote 0
Trình độ em non kém quá nên không biết dò cách nào để ra cái FormFun này. Trong đó nó có Check lựa chọn Icon luôn, nhưng sử dụng Class.
Form này thiết kế rất hay... nhưng chắc còn lâu lắm ta mới có thể áp dụng nó 1 cách thành thạo được
Vậy thì ngay bây giờ phải cố gắng trao dổi thêm thôi (để hy vọng 1 ngày không xa ta cũng làm được hoặc hơn thế)
 
Upvote 0
Thì sửa lại tí:
PHP:
Private Declare Function FindWindow Lib "User32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SetWindowLong Lib "User32" Alias "SetWindowLongA" _
(ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function SetWindowPos Lib "user32.dll" (ByVal hWnd As Long, _
ByVal hWndInsertAfter As Long, ByVal x As Long, _
ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
PHP:
Private Sub UserForm_Initialize()
Dim hWnd As Long
hWnd = FindWindow("ThunderDFrame", Me.Caption)
SetWindowPos hWnd, -2, 0, 0, 800, 600, &H40
SetWindowLong hWnd, -16, &H84CF0080
Application.Visible = False
End Sub
PHP:
Private Sub CommandButton1_Click()
Unload Me
End Sub
PHP:
Private Sub UserForm_Terminate()
Application.Visible = True
End Sub

Thầy ui, cũng để cái dòng code này: "SetWindowPos hWnd, -2, 0, 0, 800, 600, &H40" để xác định chiều rộng chiều cao của Form, nhưng em lại không muốn có cái ICON ở Taskbar (như các UserForm khác) thì code này phải sửa lại như thế nào? và cái API này khai lại như thế nào ạ?

Private Declare Function SetWindowPos Lib "user32.dll" (ByVal hWnd As Long, _
ByVal hWndInsertAfter As Long, ByVal x As Long, _
ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long

Cám ơn rất nhiều!
 
Upvote 0
Thầy ui, cũng để cái dòng code này: "SetWindowPos hWnd, -2, 0, 0, 800, 600, &H40" để xác định chiều rộng chiều cao của Form, nhưng em lại không muốn có cái ICON ở Taskbar (như các UserForm khác) thì code này phải sửa lại như thế nào? và cái API này khai lại như thế nào ạ?

Private Declare Function SetWindowPos Lib "user32.dll" (ByVal hWnd As Long, _
ByVal hWndInsertAfter As Long, ByVal x As Long, _
ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long

Cám ơn rất nhiều!

Hỏi xong rồi mày mò, rồi tự trả lời luôn! Hihihihi

Cấu trúc không cần thay gì cả, đổi số thôi:

"SetWindowPos hWnd, -2, 0, 0, 800, 600, &H40"

&H40 thực ra là 64, vậy mình đổi thành 32 hay 16, hay 0 gì đó là mất tiêu cái Icon ở Taskbar luôn!

"SetWindowPos hWnd, -2, 0, 0, 800, 600, 32"
 
Upvote 0
Tôi thấy các bạn sử dụng các hàm API mò mẫm quá. Các tham số của các hàm API là các HẮNG SỐ CÓ TÊN, nhưng các bác bỏ đi phần khai báo hằng số mà dùng luôn trị số của nó, các bác làm như vậy để thể hiện sự ngắn gọn nhưng như thế người khác không thể học tập được gì mà chỉ để áp dụng mà thôi.

Ví dụ để gửi thông điệp báo cho Window thay thế Icon trên Caption của nó.

Mã:
        [COLOR="SeaGreen"]'Set the big (32x32) and small (16x16) icons[/COLOR]
        SendMessage mhWndForm, WM_SETICON, True, hIcon
       [COLOR="SeaGreen"]'Set the small (16x16) icons[/COLOR]
        SendMessage mhWndForm, WM_SETICON, False, hIcon

hIcon la biến giữ điều khiển tới (handle to) một icon. Có thể dùng các hàm API để lấy như ExtractIcon hoặc dùng ListImages trong MSCOMCTL.OCX...

Với đoạn code trên theo các trình bày của các bạn để cho ngắn hoặc như làm ảo thuật
Mã:
        SendMessage mhWndForm, 128, True, hIcon
        SendMessage mhWndForm, 128, False, hIcon

Vậy 128 là cái gì? Nó là trị số của hằng số có tên WM_SETICON nhưng trình bày như vậy các bạn sẽ thấy đọc code không hiểu là gì.

Trên chỉ là ví dụ đơn giản, ví dụ liên quan tới thiết lập thuộc tính (Style) cho Window mới là phức tạp. Thuộc tính là sự kết hợp OR, AND, NOT các bit để Window vẽ lại cửa sổ theo cách người dùng xác lập.

Ví dụ thiết lập Form/Window vừa có nút MINIMIZEBOX và WS_MAXIMIZEBOX
Mã:
    oldStyle = GetWindowLong(mhWndForm, GWL_STYLE) [COLOR="SeaGreen"]'Nhận thuộc tính cũ[/COLOR]
   SetWindowLong mhWndForm, GWL_STYLE, oldStyle Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX [COLOR="SeaGreen"]'Kết hợp thêm thuộc tính mới[/COLOR]

Giả xử một Form đang có các nút Mini và Max giờ tôi bỏ đi thì code sẽ thế này
Mã:
    oldStyle = GetWindowLong(mhWndForm, GWL_STYLE) [COLOR="SeaGreen"]'Nhận thuộc tính cũ[/COLOR]
   SetWindowLong mhWndForm, GWL_STYLE, oldStyle Or [COLOR="Red"]Not And[/COLOR] (WS_MINIMIZEBOX Or WS_MAXIMIZEBOX) [COLOR="SeaGreen"]'Gõ bỏ thuộc tính mới[/COLOR]


Theo cách trình bày của các bạn thì nó như thế này
Mã:
   SetWindowLong mhWndForm, -16, -2067070848

Nhìn thì ngắn thật nhưng -16, -2067070848 là cái gì vậy? Sao bạn có cái này?.... Tóm lại, cách trình bày này không phải để học tập.
Bản chất -2067070848 = oldStyle + WS_MINIMIZEBOX + WS_MAXIMIZEBOX
-16 là trị số thiết lập thuộc tính Window (GWL_STYLE = -16).

Chúng ta có cách học đúng thì sẽ tự nâng cao trình độ được, còn không sẽ suốt ngày mày mò.
Góp ý trên là tôi chia sẻ về việc tiếp cận và học lập trình nói chung, API nói riêng, có gì không phải mong các bạn lượng thứ!


(Tôi không phải được học IT chuyên nghiệp theo trường lớp mà tự học như các bạn.)
 
Lần chỉnh sửa cuối:
Upvote 0
Hỏi xong rồi mày mò, rồi tự trả lời luôn! Hihihihi

Cấu trúc không cần thay gì cả, đổi số thôi:

"SetWindowPos hWnd, -2, 0, 0, 800, 600, &H40"

&H40 thực ra là 64, vậy mình đổi thành 32 hay 16, hay 0 gì đó là mất tiêu cái Icon ở Taskbar luôn!

"SetWindowPos hWnd, -2, 0, 0, 800, 600, 32"
Xem bài này cho nó tổng quát:
http://www.giaiphapexcel.com/forum/showthread.php?36636-Tổng-quan-về-UserForm-Windows-Styles
--------------------
Tôi thấy các bạn sử dụng các hàm API mò mẫm quá
Bước đầu chưa hiểu lắm nên phải mò thế Tuân à! Khi đã hiểu, đã áp dụng được 1 vài bài thì mới tính đến chuyện hoàn thiện kiến thức
Học không có căn bản nên chẳng thể 1 bước lên mây đâu!
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom