Hỏi - Cách xác định kích thước của Vùng chứa Thanh Toolbar (10 người xem)

  • Thread starter Thread starter VMH0307
  • Ngày gửi Ngày gửi
Liên hệ QC

Người dùng đang xem chủ đề này

VMH0307

Thành viên tiêu biểu
Tham gia
5/8/11
Bài viết
765
Được thích
605
Kính gửi: các Bác, Thầy và mọi người!
Mọi người cho em hỏi, em muốn xác định kích thước từ đỉnh workspace đến hết cạnh trên của thanh công thức (From the top edge of the workspace to the top edge of the formula bar) thì dùng code như thế nào ạ? (ưu tiên sử dụng đơn vị point)
Em cám ơn mọi người!
 
Kính gửi: các Bác, Thầy và mọi người!
Mọi người cho em hỏi, em muốn xác định kích thước từ đỉnh workspace đến hết cạnh trên của thanh công thức (From the top edge of the workspace to the top edge of the formula bar) thì dùng code như thế nào ạ? (ưu tiên sử dụng đơn vị point)
Em cám ơn mọi người!

1. Bạn nên chụp ảnh cửa sổ Excel --> mở Paint --> đánh dấu khoảng bạn muốn đo từ đâu tới đâu --> gửi hình lên GPE

2. Bạn nên "nhiều lời" hơn. Nói rõ mục đích chính của bạn để làm gì. Biết đâu lại có cách đi tới đích đó mà không cần tính cái khoảng cách kia?

Tốt nhất là nói mục đích chính còn phương pháp cụ thể để người khác lựa chọn. Chưa chắc con đường mà mình nghĩ "phải thế" đã là con đường duy nhất, tốt nhất.
 
Upvote 0
Mục đích của em ở đây là: Tạo 1 form hiển thị đúng vị trí và thay thế thanh công thức của excel.
Do vậy em muốn tìm vị trí của thanh công thức.
Em tìm ra 1 hướng dựa trên lời giải của các thầy ở bài này:
http://www.giaiphapexcel.com/forum/...-định-được-Top-và-Left-của-ô-A1-so-với-Window
- Rồi tính toán với các kích thước vị trí của Workspace, window, cell
có thể sử dụng 1 số hàm macro4
Application.ExecuteExcel4Macro("get.cell(42,sheet1!R1C1)")
Application.ExecuteExcel4Macro("get.cell(43,sheet1!R1C1)")
Application.ExecuteExcel4Macro("get.window(3)")
Application.ExecuteExcel4Macro("get.window(4)")
Application.ExecuteExcel4Macro("get.workspace(11)")
Application.ExecuteExcel4Macro("get.workspace(12)")
- Tính bề rộng của thanh công thức:
tính Widtch của Application sau khi điều chỉnh DisplayFormulaBar.
=> Nói chung đi khá "lắt léo", mà có thể chưa chính xác (do trình độ em còn hạn hẹp)
Vậy nên em muốn nhờ các thầy chỉ cách tính được vị trí của thanh công thức, nếu tính trực tiếp được thì tốt quá
 
Upvote 0
Mục đích của em ở đây là: Tạo 1 form hiển thị đúng vị trí và thay thế thanh công thức của excel.
Do vậy em muốn tìm vị trí của thanh công thức.
Em tìm ra 1 hướng dựa trên lời giải của các thầy ở bài này:
http://www.giaiphapexcel.com/forum/showthread.php?74444-L%C3%A0m-sao-x%C3%A1c-%C4%91%E1%BB%8Bnh-%C4%91%C6%B0%E1%BB%A3c-Top-v%C3%A0-Left-c%E1%BB%A7a-%C3%B4-A1-so-v%E1%BB%9Bi-Window
- Rồi tính toán với các kích thước vị trí của Workspace, window, cell
có thể sử dụng 1 số hàm macro4
Application.ExecuteExcel4Macro("get.cell(42,sheet1!R1C1)")
Application.ExecuteExcel4Macro("get.cell(43,sheet1!R1C1)")
Application.ExecuteExcel4Macro("get.window(3)")
Application.ExecuteExcel4Macro("get.window(4)")
Application.ExecuteExcel4Macro("get.workspace(11)")
Application.ExecuteExcel4Macro("get.workspace(12)")
- Tính bề rộng của thanh công thức:

Bạn không đọc kỹ bài của tôi rồi.
Tôi muốn giúp bạn nhưng không hiểu rõ lắm yêu cầu nên hỏi thêm. Tôi không thạo tiếng Anh, vả lại khái niệm "Workspace" tôi cũng không rõ tính từ đâu tới đâu: từ gờ trên của thanh công thức tới gờ dưới của dòng "Home Insert ..." hay từ gờ trên của thanh công thức tới gờ trên của thanh tiêu đề? Hay khác nữa?
Vì không hiểu nên tôi đề nghị chụp ảnh và đánh dấu. Tôi có quan tâm tới các bước mà bạn định làm đâu mà bạn liệt kê ra ở đây?
Tôi đã nói rõ rồi: bạn chỉ ra cần tính cái gì còn các bước thế nào, phương pháp nào là do người giúp đề nghị.

tính Widtch của Application sau khi điều chỉnh DisplayFormulaBar.

Vậy cuối cùng là tính gì? Width của vùng hay Height của vùng? Vì bạn viết "kích thước từ đỉnh workspace đến hết cạnh trên của thanh công thức", tức Height?.
Nếu cứ như thế này thì tôi xin rút lui.
Tôi nhắc lại: ảnh có đánh dấu hoặc miêu tả chính xác "độ cao" cần tính, thế thôi. Các bước bạn nghĩ, bạn thử không quan tâm.
 
Upvote 0
Mục đích của em ở đây là: Tạo 1 form hiển thị đúng vị trí và thay thế thanh công thức của excel.

Thôi tôi không đợi nữa. Tôi bỏ những phần bạn viết về ý định, hướng đi của mình. Tôi chỉ quan tâm tới 1 dòng duy nhất đã trích ở trên.
Code ví dụ sẽ xác định vị trí và kích thước của Formula Bar trên screen. Code cũng hiển thị UserForm vào vị trí nói trên để che toàn bộ Formula Bar.
Nếu không đúng ý bạn thì ráng chịu nhé.

Code Module

[GPECODE=vb]
Private Const LOGPIXELSX = 88
Private Const LOGPIXELSY As Long = 90
Private Const POINTS_PER_INCH As Long = 72
Public Const WS_CAPTION = &HC00000
Public Const GWL_STYLE = (-16)

Public Type RECT
left As Long
Top As Long
right As Long
Bottom As Long
End Type

Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function DrawMenuBar Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function GetDC Lib "user32.dll" (ByVal hWnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32.dll" (ByVal hWnd As Long, ByVal hdc As Long) As Long
Public Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function GetWindowRect Lib "user32.dll" (ByVal hWnd As Long, ByRef lpRect As RECT) As Long
Private Declare Function GetDeviceCaps Lib "gdi32.dll" (ByVal hdc As Long, ByVal nIndex As Long) As Long

Function CoordinateFormulaBar() As RECT
Dim PointsPerPixelX As Double, PointsPerPixelY As Double
Dim DC As Long, hWnd As Long, rc As RECT
Dim left As Long, right As Long
DC = GetDC(0)
PointsPerPixelX = POINTS_PER_INCH / GetDeviceCaps(DC, LOGPIXELSX)
PointsPerPixelY = POINTS_PER_INCH / GetDeviceCaps(DC, LOGPIXELSY)
ReleaseDC 0, DC

hWnd = FindWindow("XLMAIN", vbNullString)
GetWindowRect hWnd, rc

left = rc.left
right = rc.right

hWnd = FindWindowEx(hWnd, 0, "EXCEL<", vbNullString)

GetWindowRect hWnd, rc

rc.left = left * PointsPerPixelX
rc.Top = rc.Top * PointsPerPixelY
rc.right = right * PointsPerPixelX
rc.Bottom = rc.Bottom * PointsPerPixelY

CoordinateFormulaBar = rc
End Function

Sub ShowForm(frm As Object)
Dim rc As RECT
rc = CoordinateFormulaBar
With frm
.StartUpPosition = 0
.left = rc.left
.Top = rc.Top
.width = rc.right - rc.left
.height = rc.Bottom - rc.Top
.Show False
End With
End Sub

Sub Button1_Click()
ShowForm UserForm1
End Sub
[/GPECODE]

code UserForm1

[GPECODE=vb]
Private Sub HideTitlebar(ByVal hForm As Long)
Dim Style As Long, TitleHeight As Single
Style = GetWindowLong(hForm, GWL_STYLE)
TitleHeight = Me.height - Me.InsideHeight
Style = (Style And Not WS_CAPTION)
SetWindowLong hForm, GWL_STYLE, Style
Me.height = Me.height - TitleHeigh
DrawMenuBar hForm
End Sub

Private Sub UserForm_Click()
Unload Me
End Sub

Private Sub UserForm_Initialize()
Dim hForm As Long
hForm = FindWindow("ThunderDFrame", Me.Caption)
HideTitlebar hForm
End Sub
[/GPECODE]

-------------------
Cần nói thêm là tôi chỉ có Excel 2007, và cửa sổ có class là "EXCEL<". Ở Excel 2010 chẳng hạn thì có thể class sẽ khác.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Cần nói thêm là tôi chỉ có Excel 2007, và cửa sổ có class là "EXCEL<". Ở Excel 2010 chẳng hạn thì có thể class sẽ khác.

Excel 2010 cũng chạy được luôn!
Em hỏi thêm: "EXCEL<" là gì vậy anh? Chẳng lẽ là Class của thanh Formula?
--------------------------
Em có ý tưởng thế này:
- Show Formula bar
- Xác định Top của cell A1 (kết quả 1)
- Xong, Hide Formula bar
- Xác định Top của cell A1 (kết quả 2)
- Lấy kết quả 1 trừ kết quả 2 ta được chiều cao của thanh Formula
Không biết giải thuật này thế nào? (hơi cùi bắp)
 
Upvote 0

File đính kèm

Upvote 0
Excel 2010 cũng chạy được luôn!
Em hỏi thêm: "EXCEL<" là gì vậy anh? Chẳng lẽ là Class của thanh Formula?

Cả 1 dải chạy ngang màn hình gồm có 2 phần: phần trái là "Name box" có class là "Edit" còn phần phải "Formula Bar" có class là "EXCEL<"
Nhìn code thì biết tôi đã "kéo dài" cửa sổ "Formula Bar" về bên trái để nó chạy ngang hết cửa sổ. Bằng cách này thì UserForm che kín cả "Nane box" và cả "Formula Bar"
Nếu ai không muốn che "Name box" thì bỏ đoạn "kéo dài" ở sau.
-------------
Thực ra cái danh sách của bạn thanhlanh ít dùng "thường ngày". Liệt kê tất cả các cửa sổ không khó (GetWindow, FindWindow + FindWindowEx, EnumWindows + EnumChildWindows ...) nhưng rồi nhìn vào cái danh sách ấy thì người không rành làm sao biết được cái cửa sổ ở dòng vd. 128 kia nó là cửa sổ nào? Và quan trọng thì cái cửa sổ mà ta quan tâm, mà ta đang nhìn thấy nó là cửa sổ ở dòng nào?
Thực dụng hơn là đọc một cửa sổ bất kỳ mà ta đang quan tâm, mà ta đang nhìn thấy.
Tôi đã viết một code trong Delphi để dùng "hàng ngày". Tôi dịch sang VB6 vì nó gần với mọi người trên diễn đàn hơn.
Trong tập tin đính kèm có EXE để chạy luôn và cũng có project để ai có VB6 thì tự compile.
Nếu ai lười kéo về thì dưới đây tôi có toàn bộ code trong VB6, ngắn thôi.
--------------
Trước hết nói về cách dùng
Chạy tập tin EXE.
Trong ListBox luôn có thông tin về cửa sổ ở tại vị trí trỏ chuột. Và thông tin về các cửa sổ "ông tổ", tức: cửa sổ bố, cửa sổ ông, cửa sổ cụ, kỵ ... Cứ đi sâu mãi thì sẽ có ông tổ mà Parent của "ông đó" là Desktop. Ví dụ ta mở Notepad. Cái vùng trắng mà ta viết văn bản là cửa sổ có class là "Edit". Cửa sổ này có cửa sổ "bố" với class là "Notepad". Cửa sổ "Notepad" có Parent - "bố" là Desktop.
Nếu ta đưa trỏ chuột vào đồng hồ ở khay hệ thống (vào icon ở khay thì lại khác) thì ta có cửa sổ có class là "TrayClockWClass", có "bố" với class là "TrayNotifyWnd", và "ông" với class là "Shell_TrayWnd"
Nếu ta đưa trỏ chuột vào thanh công thức Excel thì thấy cửa sổ có class là "EXCEL<" (Excel 2007, 2010) mà "bố" của nó có class là "XLMAIN". Ông bố này có Parent - "bố" là Desktop.
------------
Project VB:

Mở project mới --> đặt List1 (listbox) lên Form1 --> đặt Timer1 lên Form1 --> sửa Interval của Timer thành 500 hoặc giá trị nào đó.
code:
[GPECODE=vb]
Private Type POINTAPI
x As Long
y As Long
End Type

Private Declare Function GetCursorPos Lib "user32.dll" (ByRef lpPoint As POINTAPI) As Long
Private Declare Function WindowFromPoint Lib "user32.dll" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Declare Function IsWindowUnicode Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function GetClassName Lib "user32.dll" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare Function GetWindowText Lib "user32.dll" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function GetParent Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function GetDlgCtrlID Lib "user32.dll" (ByVal hwnd As Long) As Long

Dim oldpt As POINTAPI

Private Sub Form_Load()
oldpt.x = -1
oldpt.y = -1
End Sub

Private Sub Form_Resize()
List1.Move 0, 0, Me.ScaleWidth, Me.ScaleHeight
End Sub

Private Sub Timer1_Timer()
Dim pt As POINTAPI, bufor As String, s As String
Dim size As Long, h1 As Long, h2 As Long
' đọc vị trí trỏ chuột trên screen
GetCursorPos pt
' nếu vị trí thay đổi so với lúc trước thì ...
If (pt.x <> oldpt.x) Or (pt.y <> oldpt.y) Then
' nhớ vị trí hiện hành của trỏ chuột
oldpt = pt
List1.Clear
' đọc handle của cửa sổ nằm ở vị trí trỏ chuột
h1 = WindowFromPoint(pt.x, pt.y)
' nếu cửa sổ là unicode thì nhập thông tin vào caption của Form1
If IsWindowUnicode(h1) <> 0 Then
Me.Caption = "window unicode"
Else
Me.Caption = "khong window unicode"
End If
' đọc class của cửa sổ ở vị trí trỏ chuột
bufor = String(128, Chr(0))
size = GetClassName(h1, bufor, 128)
s = Mid(bufor, 1, size)
' đọc tiêu đề của cửa sổ ở vị trí trỏ chuột
size = GetWindowText(h1, bufor, 128)
s = h1 & ", " & GetDlgCtrlID(h1) & ", " & s & ", " & Mid(bufor, 1, size)
' nhập thông tin về cửa sổ vào listbox
List1.AddItem "Handle - HWND, ID, ClassName, WindowText:"
List1.AddItem s
List1.AddItem ""
List1.AddItem ""
' thông tin về các cửa sổ "bố", "ông", "cụ", "kỵ" ...
List1.AddItem "HWND, ClassName, WindowText cua cac Parent:"
' đọc ông tổ trực tiếp của cửa sổ ở trỏ chuột, tức "bố"
h2 = GetParent(h1)
' cho tới khi ông tổ hiện hành không là Desktop thì ...
Do While h2 > 0
' đọc class của ông tổ
size = GetClassName(h2, bufor, 128)
s = Mid(bufor, 1, size)
' đọc tiêu đề của ông tổ
size = GetWindowText(h2, bufor, 128)
s = h2 & ", " & s & ", " & Mid(bufor, 1, size)
List1.AddItem s
h2 = GetParent(h2)
Loop
End If
End Sub
[/GPECODE]
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Trời! trên cả tuyệt.

--------------------------------
Cảm ơn Anh, thực ra tôi cũng đang mò mẫm nghiên cưú mấy cái này cho vui, nhưng vì năng lực có hạn nên chưa biết được là bao. Anh lại còn có diễn giải nữa chớ, chắc phải từ từ mới tiêu được. Tôi cũng đã chép code về và complete sang .exe theo hướng dẫn của anh OK.
 
Lần chỉnh sửa cuối:
Upvote 0
Trời! trên cả tuyệt.

--------------------------------
Anh lại còn có diễn giải nữa chớ, chắc phải từ từ mới tiêu được.

Những hàm API có tên rất "gợi ý". Nếu ai biết tiếng Anh thì chỉ cần đọc tên hàm thôi thì cũng mường tượng khoảng 50% là hàm sẽ làm gì. Vd. GetCursorPos (pos - position) - đọc vị trí trỏ chuột, GetParent, WindowFromPoint, GetClassName, GetWindowText
Để biết được 100% thì phải đọc help + viết code thử nghiệm.
 
Lần chỉnh sửa cuối:
Upvote 0
Những hàm API có tên rất "gợi ý". Nếu ai biết tiếng Anh thì chỉ cần đọc tên hàm thôi thì cũng mường tượng khoảng 50% là hàm sẽ làm gì.
Nếu không vậy thì cả đời chúng ta cũng đừng mong "mò" và nghiên cứu
Chính thế mà khi viết code, em cũng thích cách đặt tên hàm, tên biết kiểu như Windows đã làm (luôn thân thiện với người dùng)
Ví dụ cách mà các thành viên GPE hay làm:
Function GPE(....)
Function CT(....)
Dim TK as String
Dim CK as Double

vân vân...
Nhìn vào mà biết được mấy "cục" ấy là gì... chết liền
Ẹc... Ẹc... (lạc đề cha nó rồi)
 
Upvote 0
Web KT

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

Back
Top Bottom