Điều khiển vị trí của Shape trên UserForm

Liên hệ QC

ndu96081631

Huyền thoại GPE
Thành viên BQT
Super Moderator
Tham gia
5/6/08
Bài viết
30,703
Được thích
53,952
Tôi làm 1 file với 1 UserForm và Shape di chuyển trên đó. Có điều tôi không tài nào điều khiển được vị trí của Shape
Các bạn xem đoạn video clip này:

[video=youtube;iWywervo5O8]http://www.youtube.com/watch?v=iWywervo5O8[/video]

Các bạn cũng thấy rằng Shape chưa chạm được đến cạnh dưới và cạnh phải của UserForm mà đã "vội" chuyển hướng rồi
Xem code thì thấy chẳng có điểm nào không hợp lý cả:
PHP:
Sub TimeProc()
  On Error Resume Next
  With UserForm1
    If .CheckBox1 = False Then .Repaint
    DoEvents
    DrawEllipse lLeft, lTop, lWidth, lHeight
    If lLeft <= 0 Then wWay = 1
    If lLeft >= .Width - lWidth Then wWay = -1
    If lTop <= 0 Then hWay = 1
    If lTop >= .Height - lHeight Then hWay = -1
  End With
  lLeft = lLeft + 2 * wWay
  lTop = lTop + 2 * hWay
End Sub
Với:
- lLeft, lTop, lWidth, lHeight là vị trí và kích thước của Shape
- wWayhWay là véc tơ chỉ hướng dọc ngang
--------------------------------------------------------------------
Các bạn chạy code trong file đính kèm và xem giúp có điểm nào chưa ổn không? Giúp tôi với nhé
(Có cảm giác phải đổi các chỉ số Left, Top, Width, Height của UserForm ra đơn vị gì đó thì mới được...)
 

File đính kèm

Thêm 1 ít lệnh vào như sau sẽ thấy:

PHP:
    If lLeft < 0 Then wWay = 1
    If lLeft > .Width - lWidth Then wWay = -1: Debug.Print lLeft, lWidth, .Width
    If lTop < 0 Then hWay = 1
    If lTop > .Height - lHeight Then hWay = -1: Debug.Print lTop, lHeight, .Height

Kết quả quả là left và top đã cực đại:

Mã:
188           50            236,25 (lTop, lHeight, .Height)
 326           50            374,25 (lLeft, lWidth, .Width)

Còn nguyên nhân thì không biết (hic).
 
Upvote 0
Vẽ thêm 1 textbox:
Height = 50
Width = 50
Name = Txt1

Và thêm code vào như sau:

PHP:
    DoEvents
    DrawEllipse lLeft, lTop, lWidth, lHeight
    If lLeft <= 0 Then wWay = 1
    If lLeft >= .Width - lWidth Then wWay = -1
    If lTop <= 0 Then hWay = 1
    If lTop >= .Height - lHeight Then hWay = -1
    .Txt1.Left = lLeft
    .Txt1.Top = lTop

Thấy rằng cái Txt1 nó chạy đúng hơn:
- Tốc độ nhanh hơn
- Đường đi dài hơn
- Do đó chạm điểm dừng cùng lúc với cái ellip, nhưng điểm dừng đúng chỗ ta mong muốn.
- Kích thước cũng lớn hơn ellip.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Thêm 1 ít lệnh vào như sau sẽ thấy:

PHP:
    If lLeft < 0 Then wWay = 1
    If lLeft > .Width - lWidth Then wWay = -1: Debug.Print lLeft, lWidth, .Width
    If lTop < 0 Then hWay = 1
    If lTop > .Height - lHeight Then hWay = -1: Debug.Print lTop, lHeight, .Height

Kết quả quả là left và top đã cực đại:

Mã:
188           50            236,25 (lTop, lHeight, .Height)
 326           50            374,25 (lLeft, lWidth, .Width)

Còn nguyên nhân thì không biết (hic).
Thật ra lúc thử nghiệm em có dùng 2 TextBox để kiểm tra vị trí của Shape so với kích thước của UserForm rồi. Thấy có sai lệch và em đang mường tượng có thể nguyên nhân là: Shape do hàm API tạo ra, được đo bằng đơn vị nào đó khác với đơn vị tính trên UserForm
Mà đơn vị này là cái giống gì cũng không biết
-----------------
Còn 1 chuyện nữa: Độ sai lệch này sẽ thay đổi khi ta thay đổi kích thước UserForm
 
Upvote 0
Shape do hàm API tạo ra, được đo bằng đơn vị nào đó khác với đơn vị tính trên UserForm
Mà đơn vị này là cái giống gì cũng không biết
Có lẽ là thế. Vì khi xác định kích thước window bằng API lúc window đang maximize, nó không bao giờ bằng với kích thước của màn hình đã được set trong Display Appearance của Control Panel (thí dụ 1024 x 768), mà luôn luôn nhỏ hơn.
 
Upvote 0
Mấu chốt là ở chỗ này nè Thầy:

PHP:
Sub TimeProc()
  On Error Resume Next
  With UserForm1
    If .CheckBox1 = False Then .Repaint
    DoEvents
    DrawEllipse lLeft, lTop, lWidth, lHeight
    If lLeft <= 0 Then wWay = 1
    If lLeft >= .InsideWidth * 4 / 3 - lWidth Then wWay = -1
    If lTop <= 0 Then hWay = 1
    If lTop >= .InsideHeight * 4 / 3 - lHeight Then hWay = -1
  End With
  lLeft = lLeft + 2 * wWay
  lTop = lTop + 2 * hWay
End Sub

Nên dùng InsideWidth InsideHeight nhân với 4/3. Vì khi thử độ rộng của Shape so với chiều rộng và chiều cao của Form thì nó chỉ đạt 3/4 của Form vì vậy nên ta nhân thêm 4/3.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Sửa đơn vị đo

Trong Userform và các controls thuộc FM20.DLL (nhóm Userform) đơn vị đo đều là Twip, nhưng các đối tượng được tạo hay điều chỉnh kích cỡ trong các hàm Windows API thì lấy đơn vị đo Pixel làm chuẩn. Trong thủ tục TimeProc, anh dùng 2 dòng lệnh so sánh:
Mã:
    If lLeft >= .Width - lWidth Then wWay = -1
    If lTop >= .Height - lHeight Then hWay = -1

Có nghĩa là sử dụng 2 thuộc tính trả về độ rộng và độ cao của form là .Width và .Height đều trả về kiểu TWip. Biến lLeft, lTop là toạ được được vẽ bởi hàm API theo đơn vị tính Pixel==>Không cùng đơn vị đo==>sai lệch.

Có ít nhất 2 giải pháp khắc phục nhưng em đưa ra 1 cách đơn giản nhất là tạo 2 biến (dạng public) frmWidth, frmHeight để nhận độ rộng và độ cao của form theo đơn vị Pixel rồi dùng chúng để so sánh

code trên cần thêm và sửa lại thành


Mã:
    Dim rc As RECT
    GetClientRect hwnd, rc [COLOR="#008000"]'Hàm Windows API trả về thông số khung của form theo Pixel, biến rc (as RECT) nhận thông số này.[/COLOR]
    frmWidth = rc.Right - rc.Left
    frmHeight = rc.Bottom - rc.Top

    If lLeft >= [COLOR="#0000FF"]frmWidth[/COLOR] - lWidth Then wWay = -1
    If lTop >= [COLOR="#0000FF"]frmHeight[/COLOR] - lHeight Then hWay = -1

Em gửi file đã sửa lỗi dưới đây và thêm thuộc tính cho form có thể resize , phóng to, thu nhỏ trong khi chạy form, đối tượng Sharp nhận toạ độ ngay khi resize form.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Trong Userform và các controls thuộc FM20.DLL (nhóm Userform) đơn vị đo đều là Twip, nhưng các đối tượng được tạo hay điều chỉnh kích cỡ trong các hàm Windows API thì lấy đơn vị đo Pixel làm chuẩn. Trong thủ tục TimeProc, anh dùng 2 dòng lệnh so sánh:
Mã:
    If lLeft >= .Width - lWidth Then wWay = -1
    If lTop >= .Height - lHeight Then hWay = -1

Có nghĩa là sử dụng 2 thuộc tính trả về độ rộng và độ cao của form là .Width và .Height đều trả về kiểu TWip. Biến lLeft, lTop là toạ được được vẽ bởi hàm API theo đơn vị tính Pixel==>Không cùng đơn vị đo==>sai lệch.

Có ít nhất 2 giải pháp khắc phục nhưng em đưa ra 1 cách đơn giản nhất là tạo 2 biến (dạng public) frmWidth, frmHeight để nhận độ rộng và độ cao của form theo đơn vị Pixel rồi dùng chúng để so sánh

code trên cần thêm và sửa lại thành


Mã:
    Dim rc As RECT
    GetClientRect hwnd, rc [COLOR=#008000]'Hàm Windows API trả về thông số khung của form theo Pixel, biến rc (as RECT) nhận thông số này.[/COLOR]
    frmWidth = rc.Right - rc.Left
    frmHeight = rc.Bottom - rc.Top

    If lLeft >= [COLOR=#0000FF]frmWidth[/COLOR] - lWidth Then wWay = -1
    If lTop >= [COLOR=#0000FF]frmHeight[/COLOR] - lHeight Then hWay = -1

Em gửi file đã sửa lỗi dưới đây và thêm thuộc tính cho form có thể resize , phóng to, thu nhỏ trong khi chạy form, đối tượng Sharp nhận toạ độ ngay khi resize form.
Tôi cũng vừa tìm ra 1 giải pháp, dùng thêm hàm GetWindowRect
- Đầu tiên khi Form load, ta sẽ lấy vị trí Left, Top, Right, Botton của UserForm
- Khi Shape di chuyển, ta sẽ so sánh vị trí của nó với 4 thông số vừa lấy ở trên
Code như sau:
1> Trong module tôi thêm cái này:
PHP:
Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long

Public Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type
Public Rec As RECT
PHP:
Sub TimeProc()
  On Error Resume Next
  With UserForm1
    If .CheckBox1 = False Then .Repaint
    DoEvents
    DrawEllipse lLeft, lTop, lWidth, lHeight
    If lLeft <= 0 Then wWay = 1
    If lLeft >= Rec.Right - Rec.Left - lWidth Then wWay = -1
    If lTop <= 0 Then hWay = 1
    If lTop >= Rec.Bottom - Rec.Top - (.Height - .InsideHeight) - lHeight Then hWay = -1
  End With
  lLeft = lLeft + 2 * wWay
  lTop = lTop + 2 * hWay
End Sub
2> Trong UserForm
PHP:
Private Sub UserForm_Activate()
  Me.Repaint
  hwnd = FindWindow("ThunderDFrame", Me.Caption)
  hDC = GetDC(hwnd)
  lLeft = 0
  lTop = 0
  lWidth = 50
  lHeight = 50
  wWay = 1
  hWay = 1
  GetWindowRect hwnd, Rec
End Sub
Tôi chạy thấy rất ổn (cảm giác hình như giống với thuật toán của Tuân). Tuy nhiên vẫn nhờ Tuân xem lại coi có điều gì chưa ổn không?
Tôi vẫn chưa hình dung sự khác nhau giữa GetClientRectGetWindowRect, nhờ Tuẩn giải thích thêm (không biết có phải thằng GetClientRect nó tính kích thước đã trừ thanh Title không nhỉ)
Cảm ơn nhé!
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Anh dự đoán là đúng, hàm GetClientRect và GetWindowRect đều lấy vị trí và kích cỡ của form, riêng hàm GetWindowRect là tính phần title/caption của form còn hàm GetClientRect thì không. Trong ví dụ của anh chỉ nên dùng hàm GetClientRect vì sharp chỉ chạy trong phạm vi client.

Thêm 2 vấn đề lưu ý vào ví dụ của anh:

1. Chuyển toàn bộ code trong sự kiện UserForm_Activate() sang UserForm_Initialize() . Sự kiện UserForm_Activate chỉ nên dùng khi muốn chạy code mỗi lần thanh title/caption được kích hoạt sáng hay form/window từ trạng thái inactive sang active.

2. Trong code có đoạn hDC = GetDC(hwnd) thì khi không dùng đến phải giải phóng chúng, có thể viết trong sự kiện UserForm_Terminate() với lệnh ReleaseDC hwnd, hDC
ReleaseDC là hàm Windows API.
 
Upvote 0
Anh dự đoán là đúng, hàm GetClientRect và GetWindowRect đều lấy vị trí và kích cỡ của form, riêng hàm GetWindowRect là tính phần title/caption của form còn hàm GetClientRect thì không. Trong ví dụ của anh chỉ nên dùng hàm GetClientRect vì sharp chỉ chạy trong phạm vi client.

Thêm 2 vấn đề lưu ý vào ví dụ của anh:

1. Chuyển toàn bộ code trong sự kiện UserForm_Activate() sang UserForm_Initialize() . Sự kiện UserForm_Activate chỉ nên dùng khi muốn chạy code mỗi lần thanh title/caption được kích hoạt sáng hay form/window từ trạng thái inactive sang active.

2. Trong code có đoạn hDC = GetDC(hwnd) thì khi không dùng đến phải giải phóng chúng, có thể viết trong sự kiện UserForm_Terminate() với lệnh ReleaseDC hwnd, hDC
ReleaseDC là hàm Windows API.
Phù... thế là xong 1 bài toán
Làm cái trò này lúc đầu chỉ để chơi, nhưng tôi dự tính nếu dùng nó để vẽ 1 biểu đồ cột đơn giản thì chẳng khó khăn gì (thay shape hình tròn bằng hình chữ nhật)
-------------------
Nhân đây xin hỏi Tuân 1 vấn đề: Không biết có hàm nào có khả năng tô màu cho mấy cái shape ấy không? (đang tìm nhưng chưa ra)
 
Upvote 0
Phù... thế là xong 1 bài toán
Làm cái trò này lúc đầu chỉ để chơi, nhưng tôi dự tính nếu dùng nó để vẽ 1 biểu đồ cột đơn giản thì chẳng khó khăn gì (thay shape hình tròn bằng hình chữ nhật)
-------------------
Nhân đây xin hỏi Tuân 1 vấn đề: Không biết có hàm nào có khả năng tô màu cho mấy cái shape ấy không? (đang tìm nhưng chưa ra)

Có chứ anh. Để tô màu ta quan tâm tới 2 hàm:
+ CreatePen() - Tạo kiểu nét và màu
+ CreateSolidBrush() hoặc CreateBrushIndirect() - Tạo màu tô và kiểu tô

Ví dụ dạng mô phỏng

hPen = CreatePen(vbBlue) - Tạo nét màu xanh
hBrush = CreateSolidBrush(vbYellow) - Tạo màu tô vàng

Thiết lập màu vào hDC (handle to device context) - Thiết bị vẽ

hPrevPen = SelectObject(hDC, hPen)
hPrevBrush = SelectObject(hDC, hBrush)

Các hàm để vẽ sẽ nhận kiểu viền, màu và nền, kiểu nền đã thiết lập ở trên

Vẽ hình chữ nhật
Rectangle(hDC, 10, 10, 200, 150)

Vẽ hình elip
Rectangle(hDC, 10, 10, 100, 100)

Tất cả các hình trên đều có nét liền màu xanh và được tô màu vàng.

Kết thúc việc vẽ, hoàn trả bộ màu cũ và giải phóng bộ nhớ

+ Hoàn trả màu cũ

SelectObject hDC, hPrevPen
SelectObject hDC, hPrevBrush

+ GIải phóng bộ nhớ

DeleteObject hPen
DeleteObject hBrush


Nói chung lập trình Windows API rất phong phú bởi hệ điều hành đã cung cấp tất cả các bộ hàm để làm trong các lĩnh vực. Các phần mềm có các giao diện đẹp, các bộ vẽ, các chương trình nghe nhạc, kết nối mạng đều dùng các hàm API mà thôi. Học tốt các hàm API có thể làm được rất nhiều điều.
 
Upvote 0
Trong VB6 thì không có vấn đề. Ở đây là VBA, tôi đang thắc mắc làm sao Get được hDC của Shape?
Trong VBA, hình như chỉ lấy được hDC của mỗi UserForm mà thôi hay sao ấy... Vậy làm sao SelectObject chính xác cái thằng Ellipse đây?
Hay Tuân làm 1 ví dụ nhỏ giúp tôi với
 
Upvote 0
Phương pháp vẽ trên Windows

Trong VB6 thì không có vấn đề. Ở đây là VBA, tôi đang thắc mắc làm sao Get được hDC của Shape?
Trong VBA, hình như chỉ lấy được hDC của mỗi UserForm mà thôi hay sao ấy... Vậy làm sao SelectObject chính xác cái thằng Ellipse đây?
Hay Tuân làm 1 ví dụ nhỏ giúp tôi với

Trong lập trình đồ hoạ của Windows là cần có điều khiển vẽ hDC (handle to device context), hDC được lấy từ hwnd (handle to window) bằng hàm và lệnh hDC = GetDC(hwnd)

Windows quản lý các cửa sổ thông qua hwnd, hwnd được tạo ra từ hàm API hwnd = CreateWindow(). Tất cả các màn hình, các điều khiển trên màn hình đều là window, và Windows cung cấp các hàm để lấy được các handle này, như GetActiveWindow(), FindWindow,...

Trên mỗi window người ta cung cấp các điều khiển khác, như thiết bị vẽ hDC để cho phép người ta vẽ lên đó các hình, viết chữ với các kiểu vẽ, mù sắc khác nhau.

Quy tắc vẽ trong Windows là
1. Chọn bút vẽ với kiểu và màu của nét
2. Chọn màu và kiểu tô
3. Thực hiện việc vẽ các hình

Các hình được vẽ (sharp) trên form/window không phải là một handle/hwnd, chúng được vẽ trên cùng một hDC. Vậy muốn xác lập kiểu, màu, chữ cho hình vẽ hay chữ viết là phải thiết lập lên hDC.

Mã:
Option Explicit
Dim oldBrush&, oldPen&, NewBrush&, NewPen&

Private Sub UserForm_Initialize()
    hwnd = FindWindow("ThunderDFrame", Me.Caption)[COLOR="#008000"] 'Nhận điều khiển của window (handle to window = hwnd)[/COLOR]
    hdc = GetDC(hwnd) [COLOR="#008000"]'Nhận điều khiển vẽ của hwnd (handle to device context = hDC)[/COLOR]
    
  [COLOR="#008000"] 'Tạo bút vẽ với màu và kiểu nét - Màu xanh, nét liền[/COLOR]
    NewPen = CreatePen(PS_SOLID, 2, vbBlue) [COLOR="#008000"]'line color and style[/COLOR]
  [COLOR="#008000"] 'Tạo màu và kiểu tô- Màu và và tô mịn (Solid)[/COLOR]
    NewBrush = CreateSolidBrush(vbYellow)[COLOR="#008000"] ' backcolor[/COLOR]
    
    'Thiết lập bút vẽ và màu tô cho [B]hDC[/B]. Các hàm vẽ sau này sẽ được vẽ bởi viền xanh và được tô màu vàng
    oldPen = SelectObject(hdc, NewPen) [COLOR="#008000"]'line color and style[/COLOR]
    oldBrush = SelectObject(hdc, NewBrush)[COLOR="#008000"] 'backcolor and style[/COLOR]
    
[COLOR="#008000"]    'oldPen là biến lưu bút vẽ trước đây, nó cần được hoàn trả khi không vẽ nữa
    'oldBrush là biến kiểu tô màu trước đây, nó cần được hoàn trả khi không vẽ nữa
    'SelectObject là hàm chọn đối tượng cho các thiết bị - Đây là hàm đan năng.[/COLOR]
End Sub

Kết thúc vẽ hay thoát form, cần hoàn trả thiết lập cũ của nó và giải phóng bộ nhớ đã bị chiếm dụng bới các biến nhận giá trị các hàm CreateXXXX()
Mã:
Private Sub UserForm_Terminate()
    [COLOR="#008000"]'Hoàn trả các thiết lập trước cho hDC[/COLOR]
    SelectObject hdc, oldPen [COLOR="#008000"]'hoàn trả bút vẽ[/COLOR]
    SelectObject hdc, oldBrush [COLOR="#008000"]'hoàn trả màu tô[/COLOR]
    
    [COLOR="#008000"]'Giải phóng bộ nhớ[/COLOR]
    DeleteObject NewPen
    DeleteObject NewBrush
    ReleaseDC hwnd, hdc
End Sub
Lưu ý rằng, các biến NewPen, NewBrush, hdc nhận giá trị của các hàm CreateXXXX, Windows phân phối một vùng nhớ cho nó, địa chỉ là một kiểu Long. Các biến này không phải lưu giữ một số nguyên thông thường nên VB không tự giải phóng bộ nhớ khi thoát thủ tục. Nhất thiết phải được giải phóng chúng khi không dùng nữa, khi đó Resource của Windows sẽ được giảm tải.

File em gửi kèm dưới đây là một ví dụ hoàn chỉnh về thiết lập màu và viền cho sharp.


(Các từ window là chỉ về một cửa sổ hoặc form; Windows là chỉ hệ điều hành; Windows API là lập trình sử dụng các hàm, thủ tục do hệ điều hành cung cấp và phương pháp can thiệp vào thành phần của hệ điều hành)
 

File đính kèm

Upvote 0
Tới đây thì có vẽ hơi khó hiểu rồi
Nghĩ cũng lạ thật. hDC được lấy từ hWnd. Mà hWnd rõ ràng là đang "ám chỉ" đến cái UserForm. Chẳng có chổ nào cho thấy đang nói đến cái hình tròn kia, ấy thế mà nó vẫn tô màu được chính xác hình tròn???
Hic...
Tạm áp dụng, mai này sẽ nghiên cứu thêm, hy vọng "ngộ" ra được vấn đề
------------------------------------------------------
Hỏi Tuân thêm 1 vấn đề nữa:
- Vì dùng UserForm.Repaint nên khi chuyển động, màn hình có vẽ giật giật, không được mượt mà cho lắm
- Vậy nếu muốn những chuyển động này mượt mà hơn thì cần phải thêm những gì?
Làm phiền quá, Tuân thông cảm nha (vì cái tham vọng của tôi chưa thể dừng ở đây)
 
Lần chỉnh sửa cuối:
Upvote 0
Tới đây thì có vẽ hơi khó hiểu rồi
Nghĩ cũng lạ thật. hDC được lấy từ hWnd. Mà hWnd rõ ràng là đang "ám chỉ" đến cái UserForm. Chẳng có chổ nào cho thấy đang nói đến cái hình tròn kia, ấy thế mà nó vẫn tô màu được chính xác hình tròn???
Hic...
Tạm áp dụng, mai này sẽ nghiên cứu thêm, hy vọng "ngộ" ra được vấn đề
------------------------------------------------------
Hỏi Tuân thêm 1 vấn đề nữa:
- Vì dùng UserForm.Repaint nên khi chuyển động, màn hình có vẽ giật giật, không được mượt mà cho lắm
- Vậy nếu muốn những chuyển động này mượt mà hơn thì cần phải thêm những gì?
Làm phiền quá, Tuân thông cảm nha (vì cái tham vọng của tôi chưa thể dừng ở đây)

Hiểu nôm na như coi hDC của form là một tờ giấy, NewPen, NewBrush là địa chỉ chứa cái bút và hộp màu vẽ.

SelectObject(hDC, NewPen)
SelectObject(hDC, NewBrush)

Hai lệnh trên là chọn bút vẽ và hộp màu cho tờ giấy để chuẩn bị vẽ. Các hàm vẽ tự động dùng cái bút và hộp màu để vẽ lên tờ giấy - hDC


UserForm.Repaint là vẽ lại (hay cập nhật lại) toàn bộ form nên ta nhìn thất nó giật giật.

Giải pháp:
Xoá cái hình vẽ lần trước rồi mới vẽ cái hình lần này
Có nghĩa là, toạ độ cũ là (1,1) vị trí mới là (1,2), ta xoá hình ở toạ độ (1,1) sau đó mới vẽ hình hở toạ độ (1,2)
Theo cách làm cũ, dùng Repaint bản chất là xoá toàn bộ màn hình sau đó mởi vẽ (1,2)
Vậy thay vì xoá cả form ta chỉ xoá một hình chữ nhật bao hình ở toạ độ (1,1)

Mẹo: tô màu một hình chữ nhật với màu trung với màu nền của form vào vị trí (1,1) thì đó là xoá.
 
Lần chỉnh sửa cuối:
Upvote 0
Lại làm phiền Tuấn thêm lần nữa:
Bạn có thể giúp tôi với file như trên nhưng tạo ra 2 hình tròn, 1 cái màu đỏ và 1 cái màu vàng được không?
Tôi muốn thông qua code để có thể hiểu thêm về hDC đấy mà
Cảm ơn trước nha!
 
Upvote 0
Lại làm phiền Tuấn thêm lần nữa:
Bạn có thể giúp tôi với file như trên nhưng tạo ra 2 hình tròn, 1 cái màu đỏ và 1 cái màu vàng được không?
Tôi muốn thông qua code để có thể hiểu thêm về hDC đấy mà
Cảm ơn trước nha!

Em viết một thủ tục tạo Sharp. Các tham số của thủ tục cho phép ta vẽ trên hDC, màu viền & màu nền, tại toạ độ X, Y với độ rộng Width, độ cao Height

Mã:
Sub CreateSharp(ByVal hDC As Long, ByVal LineColor As Long, ByVal FillColor As Long, _
                    ByVal X As Long, _
                    ByVal Y As Long, _
                    ByVal Width As Long, _
                    ByVal Height As Long)
                    
    Dim hNewPen&, hNewBrush&, hPrevPen&, hPrevBrush&
    hNewPen = CreatePen(PS_SOLID, 2, LineColor)[COLOR="#008000"] 'line color and style[/COLOR]
    hNewBrush = CreateSolidBrush(FillColor) [COLOR="#008000"]' backcolor[/COLOR]
    
    [COLOR="#008000"]'Set color for sharp[/COLOR]
    hPrevPen = SelectObject(hDC, hNewPen)[COLOR="#008000"] 'line color and style[/COLOR]
    hPrevBrush = SelectObject(hDC, hNewBrush) [COLOR="#008000"]'backcolor and style[/COLOR]
   [COLOR="#008000"] 'Draw[/COLOR]
    Ellipse hDC, X, Y, X + Width, Y + Height
    
    [COLOR="#008000"]'Restore previous Pen & Brush[/COLOR]
    SelectObject hDC, hPrevPen
    SelectObject hDC, hPrevBrush
    
    [COLOR="#008000"]'Free Mem[/COLOR]
    DeleteObject hNewPen
    DeleteObject hNewBrush
        
End Sub

Trong Userform, anh tạo một nút bấm (CommandButton3), mở sự kiện CommandButton3_Click và dán đoạn code tạo 2 hình tròn với màu vàng và màu đỏ như dưới đây.

Mã:
Private Sub CommandButton3_Click()
    [B]CreateSharp[/B] hDC, vbBlue, vbYellow, 10, 10, 100, 100
    [B]CreateSharp[/B] hDC, vbYellow, vbRed, 10, 200, 100, 100
End Sub
 
Upvote 0
Em viết một thủ tục tạo Sharp. Các tham số của thủ tục cho phép ta vẽ trên hDC, màu viền & màu nền, tại toạ độ X, Y với độ rộng Width, độ cao Height
Quà thật mấy cái trò API này càng học càng thấy hấp dẫn nhưng cũng đổ mồ hôi hột không ít
Cảm ơn Tuân nhiều! Code mới có thể "tiêu hóa" được
Ẹc... Ẹc...
 
Upvote 0
Phù... Sau 2 ngày "cày như trâu", cuối cùng cũng điều khiển được shape theo ý muốn

[video=youtube;daWcaYOuRjk]http://www.youtube.com/watch?v=daWcaYOuRjk[/video]

Mời xem file!
Cảm ơn Tuân rất nhiều, cảm ơn các bạn đã quan tâm
(Nói thật, điều khiển shape chẳng để ứng dụng gì cả, chỉ là dợt các hàm API cho lên tay thôi, mai này sẽ làm những việc khác...)
 

File đính kèm

Upvote 0
bác ơi, em ko xem dc code,em ko rõ về phần làm quả bóng chuyển động, phan xạ,mong bác chỉ giáo cho chút ít, bác reply lại cho em nha.Ca?m ơn bác
nhiều
 
Upvote 0
Web KT

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

Back
Top Bottom