#HookLab - Tạo cửa sổ TaskPane / ActionPane bằng UserForm

Liên hệ QC

thaipv

XA Project
Tham gia
18/5/14
Bài viết
158
Được thích
239
Giới tính
Nam
Gửi tặng các bạn mã nguồn để tạo cửa sổ TaskPane / ActionPane (cửa sổ phụ) trong excel bằng UserForm.219359
Ghi chú : Cửa sổ con di chuyển trong phạm vi bên trong và di chuyển theo cửa sổ cha của nó.
+ Màu cam : Cửa sổ ông nội XLMAIN
+ Màu đỏ : Cửa sổ cha XLDESK
+ Màu tím : Cửa sổ con EXCEL7

Giải thuật vắn tắt :
1. Thiết lập UserFom làm (giả) TaskPane / ActionPane là con của cửa sổ XLDESK (con nuôi).
2. Sắp xếp lại vị trí của UserForm và EXCEL7 (con ruột) sao cho không đè lên nhau (UserForm có thể ở bên trái hoặc bên phải của EXCEL7...).
3. Mỗi khi cửa sổ cha XLDESK thay đổi vị trí hoặc kích thước thì cửa sổ con cũng thay đổi theo (và trở về mặc định). Vì vậy, ta cần đặt 1 hook bắt sự kiện này để UserForm và EXCEL7 định lại vị trí và kích thước theo đúng ý 2.
 

File đính kèm

  • FacePane.xlsm
    45 KB · Đọc: 187
Upvote 0
Sao VBA nó ko hổ trợ TaskPanes mà mình cứ loanh quanh làm giả khổ quá nhỉ ===\.
thấy link sau nó có hướng dẫn mã chưa test ko biết là cho Excel hay Word nữa
Mới kiếm được sách xong thích khúc code nào copy cho nhanh trên File PDF úp cho ai iu em nó
 

File đính kèm

  • Excel 2007 VBA 参考手册(PDF,ENG).rar
    5.5 MB · Đọc: 108
Lần chỉnh sửa cuối:
Upvote 0
Code cũ của bạn trong mHooklab là:
Mã:
#If VBA7 Then
   ...
    Public Function xlDeskProc(ByVal hWnd As LongPtr, ByVal uMsg As Long, _
                               ByVal wParam As Long, ByVal lParam As Long) As LongPtr
        If WM_SIZE = uMsg Then
            Call frmTaskPane.SetLayout
        Else
            If 0 = lpPrevProc Then Call RecoverPointer(lpPrevProc, "lpPrevProc")
            If 0 <> lpPrevProc Then
                xlDeskProc = CallWindowProc(lpPrevProc, hWnd, uMsg, wParam, lParam)
            End If
        End If
    End Function
#Else
...
#End If

Trong môi trường 64-bit thì tham số LPARAM, WPARAM là số Long 8 byte vì thế hàm xlDeskProc bạn phải sửa lại kiểu của hai tham số này. Cần sửa lại như sau:

Mã:
#If VBA7 Then
   ...
    Public Function xlDeskProc(ByVal hWnd As LongPtr, ByVal uMsg As Long, _
                               ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
        If WM_SIZE = uMsg Then
            Call frmTaskPane.SetLayout
        Else
            If 0 = lpPrevProc Then Call RecoverPointer(lpPrevProc, "lpPrevProc")
            If 0 <> lpPrevProc Then
                xlDeskProc = CallWindowProc(lpPrevProc, hWnd, uMsg, wParam, lParam)
            End If
        End If
    End Function
#Else
...
#End If

Mình góp ý thêm là các khai báo hàm API của bạn nên sửa lại cho gọn, liên quan đến các hàm SetWindowLongPtrA, GetWindowLongPtrA
Mã:
    #If Win64 Then
        Public Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongPtrA" ( _
            ByVal hWnd As LongPtr, _
            ByVal nIndex As Long, _
            ByVal dwNewLong As LongPtr) As LongPtr
    #Else
        Public Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongA" ( _
            ByVal hWnd As LongPtr, _
            ByVal nIndex As Long, _
            ByVal dwNewLong As LongPtr) As LongPtr
    #End If

Sửa lại là
Mã:
    #If Win64 Then
        Public Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongPtrA" ( _
            ByVal hWnd As LongPtr, _
            ByVal nIndex As Long, _
            ByVal dwNewLong As LongPtr) As LongPtr
    #Else
        Public Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" ( _
            ByVal hWnd As LongPtr, _
            ByVal nIndex As Long, _
            ByVal dwNewLong As LongPtr) As LongPtr
    #End If

Khi đưa về một tên SetWindowLong thì sau này sử dụng nó bạn không phải điều hướng biên dịch #If VBA7 nữa thì code sẽ ngắn gọn hơn.
Trong các code liên quan tới điều hướng 32 và 64-bit chưa được gọn (phải viết lại nguyên một hàm). Chỉ nên điều hướng những dòng code , những khai báo có kiểu dữ liệu khác nhau, code bên trong Sub, Function nên đồng bộ cả 32 và 64 bit sau này bảo trì và nâng cấp thuận lợi hơn.

Dự án liên quan đến API - subclass trong VBA này còn nhiều gian nan lắm. Còn rất nhiều việc khác bạn phải nâng cấp nữa.
 

File đính kèm

  • TaskPane_Fix02.xlsm
    37.4 KB · Đọc: 141
Lần chỉnh sửa cuối:
Upvote 0
Đúng cái mình cần, chỉ cần Add là sài. Cảm ơn bạn rất nhiều vì đã chia sẽ
 
Upvote 0
Thấy Bill nói trên Vb có vẻ đơn giản thế mà VBA nó không hổ trợ thấy buồn ... có cách nào lách xài không nhỉ
Code Của Bill
Mã:
Private myUserControl1 As MyUserControl
Private WithEvents myCustomTaskPane As Microsoft.Office.Tools.CustomTaskPane

Private Sub ThisAddIn_Startup(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Me.Startup

    myUserControl1 = New MyUserControl()
    myCustomTaskPane = Me.CustomTaskPanes.Add(myUserControl1, "New Task Pane")

    With myCustomTaskPane
        .DockPosition = Office.MsoCTPDockPosition.msoCTPDockPositionFloating
        .Height = 500
        .Width = 500
        .DockPosition = Office.MsoCTPDockPosition.msoCTPDockPositionRight
        .Width = 300
        .Visible = True
    End With
End Sub
Mã:
[System.Runtime.InteropServices.Guid("c3a84bf1-e95b-4d23-952d-59e35673958e")]
public interface CustomTaskPaneCollection : 
IDisposable, System.Collections.Generic.IEnumerable<Microsoft.Office.Tools.CustomTaskPane>
 
Upvote 0
Thấy Bill nói trên Vb có vẻ đơn giản thế mà VBA nó không hổ trợ thấy buồn ... có cách nào lách xài không nhỉ
Code Của Bill
Mã:
Private myUserControl1 As MyUserControl
Private WithEvents myCustomTaskPane As Microsoft.Office.Tools.CustomTaskPane

Private Sub ThisAddIn_Startup(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Me.Startup

    myUserControl1 = New MyUserControl()
    myCustomTaskPane = Me.CustomTaskPanes.Add(myUserControl1, "New Task Pane")

    With myCustomTaskPane
        .DockPosition = Office.MsoCTPDockPosition.msoCTPDockPositionFloating
        .Height = 500
        .Width = 500
        .DockPosition = Office.MsoCTPDockPosition.msoCTPDockPositionRight
        .Width = 300
        .Visible = True
    End With
End Sub
Mã:
[System.Runtime.InteropServices.Guid("c3a84bf1-e95b-4d23-952d-59e35673958e")]
public interface CustomTaskPaneCollection :
IDisposable, System.Collections.Generic.IEnumerable<Microsoft.Office.Tools.CustomTaskPane>
Dường như là không có cách nào tạo TaskPane theo cách 'chính thống' trong VBA được. Tài liệu bạn gửi ở bài #22 cũng yêu cầu 1 COM-Addin.
 
Upvote 0
Em CustomTaskPane ... Mạnh làm đang hình thành thai nghén ... khoe một tẹo he
Viết *.OCX luôn he :p
Vậy là trên GPE Mạnh là người thứ 2 Viết *.OCX CustomTaskPane sau sư Phụ @Nguyễn Duy Tuân .... Coder Đẳng Cấp đó he ;)
View attachment 228374

Đúng hướng rồi. Tham số myUserControl là Form ActiveX. Bạn chú ý sử dụng các thuộc tính Align hoặc Anchors để căn chỉnh các controls theo Form là ok đấy.
 
Upvote 0
Em CustomTaskPane ... Mạnh làm đang hình thành thai nghén ... khoe một tẹo he
Viết *.OCX luôn he :p
Vậy là trên GPE Mạnh là người thứ 2 Viết *.OCX CustomTaskPane sau sư Phụ @Nguyễn Duy Tuân .... Coder Đẳng Cấp đó he ;)
View attachment 228374
Anh number one :victory:

Chỉ em với hhihihi-=.,,

MỚI bắt đầu còn nhiều thứ lỗi lắm
anh viết bằng gì vậy ?
 
Upvote 0
Co và giản kéo và thả 4 góc Excel thoải mái... thấy tiện ích :p
Mỗi ngày điều chỉnh viết thêm vô một chút ... chơi mà học .... học mà chơi vậy mới vui khi mò ra một cái gì đó

Capture.JPG
 
Upvote 0
hihi nếu anh viết trên Delphi còn nhứt đầu nhiều lắm :wiggle:
 
Upvote 0
hihi nếu anh viết trên Delphi còn nhứt đầu nhiều lắm :wiggle:
Sư phụ lâu nay vẫn có và đang xài đó còn giả vờ hỏi sao ???!!!!

Nếu thích thì có thể tải cuốn sách bài #22 nghiên cứu là có thể làm được theo cách của Sư phụ he ;);)
 
Upvote 0
Sư phụ lâu nay vẫn có và đang xài đó còn giả vờ hỏi sao ???!!!!

Nếu thích thì có thể tải cuốn sách bài #22 nghiên cứu là có thể làm được theo cách của Sư phụ he ;);)
Lâu rồi em đâu có sài nó, nó còn lỗi gõ tiếng việt lâu lâu nó đơ đơ em chưa giải quyết được (có thể do em chưa biết làm)?
 
Upvote 0
:wallbash: Cực lắm :bye2:
Em có thử viết cái OCX mà nhắm không đủ sức làm nên thôi
View attachment 228455
Mạnh thấy VB6 cũng viết tốt có điều nó lỗi thời ko hổ trợ nữa và chỉ chạy trên nền tảng x32 ... còn x64 thì mạnh ko biết
không biết có cách nào viết *.OCX trên VB6 xong chuyển nó qua Delphi build x32_x64 được ko nhỉ ??? ( Vì mình có thể làm tốt trên VB6 còn Delphi thì thua)
 
Upvote 0
Mạnh thấy VB6 cũng viết tốt có điều nó lỗi thời ko hổ trợ nữa và chỉ chạy trên nền tảng x32 ... còn x64 thì mạnh ko biết
không biết có cách nào viết *.OCX trên VB6 xong chuyển nó qua Delphi build x32_x64 được ko nhỉ ??? ( Vì mình có thể làm tốt trên VB6 còn Delphi thì thua)
-+*/:''" Kiến thức em thì em bó tay anh ơi hông có đơn giản đâu viết thì có thể nó chạy đó mà nó chạy có ổn không thì không biết, lỗi tràn bộ nhớ v.v.v......
 
Upvote 0
Web KT
Back
Top Bottom