Chia sẻ cách tạo giao diện cho Form

giaiphap

Thành viên gạo cội
Tham gia ngày
12 Tháng ba 2007
Bài viết
4,676
Được thích
3,860
Điểm
860
Mình thấy giao diện Form excel tương đối đơn điệu, qua tìm hiểu về cách tạo form có hình dạng bất kỳ. Hôm nay mình có sưu tầm đoạn code cho file excel có sử dụng hình ảnh bất kỳ để tạo giao diện cho Form, mình chia sẻ để mọi người phát triển nhằm làm phong phú thêm giao diện Form của excel.

220943
 

File đính kèm

Chỉnh sửa lần cuối bởi điều hành viên:

Nguyễn Duy Tuân

Nghị Hách
Thành viên danh dự
Tham gia ngày
13 Tháng sáu 2006
Bài viết
4,080
Được thích
9,532
Điểm
860
Nơi ở
Hà Nội
Để giảm bị "lem nhem" mầu trắng thì bạn thử cách sau.

1. Thiết kế ảnh sao cho, nền của anh mà mình muốn Trasparent phải có màu đặc biệt, khác chủ màu của cần hiển thị của anh. Ví dụ object hiển thị không có màu vbBlue thì dùng nền vbBlue
2. Trong code mwor form sửa lại lệnh là
BackColor = vbBlue
MakeUserFormTransparent Me, vbBlue 'make certain color transparent

Ví dụ của mình là màu vbBlue là nền của bức ảnh.
 

ThangCuAnh

Thành viên tích cực
Tham gia ngày
1 Tháng mười hai 2017
Bài viết
490
Được thích
373
Điểm
210
Nơi ở
Phờ lây cu
Hay nhỉ, nhanh đó chứ. SetLayeredWindowAttributes, mình quên béng hàm này.
Hồi xưa code mấy cái transparent, hoạt hình trên Win 3x, 9x cực bỏ bu.
Bác @giaiphap sao không dùng cái này làm skin mà dùng cách code skin theo kiểu cũ, GetPixel, SetPixel... trên C/C++ còn chạy chậm bỏ cha.
Hàm này và hàm TransparentBlt sau này mới có từ Win2000
 
Lần chỉnh sửa cuối:

giaiphap

Thành viên gạo cội
Tham gia ngày
12 Tháng ba 2007
Bài viết
4,676
Được thích
3,860
Điểm
860
Để giảm bị "lem nhem" mầu trắng thì bạn thử cách sau.

1. Thiết kế ảnh sao cho, nền của anh mà mình muốn Trasparent phải có màu đặc biệt, khác chủ màu của cần hiển thị của anh. Ví dụ object hiển thị không có màu vbBlue thì dùng nền vbBlue
2. Trong code mwor form sửa lại lệnh là
BackColor = vbBlue
MakeUserFormTransparent Me, vbBlue 'make certain color transparent

Ví dụ của mình là màu vbBlue là nền của bức ảnh.
2 vấn đề này thì em biết và đã thử luôn rồi, màu nền em design bằng Photoshop luôn anh nên màu nền là chính xác luôn, nhưng dùng code không được ngoài trừ màu trắng. Em cũng chấp nhận design lại tất cả các màu trắng trên form trừ màu nền, nhưng không biết sao code lại chạy không chính xác bị "lem nhem" như anh nói.
Bài đã được tự động gộp:

Hay nhỉ, nhanh đó chứ. SetLayeredWindowAttributes, mình quên béng hàm này.
Hồi xưa code mấy cái transparent, hoạt hình trên Win 3x, 9x cực bỏ bu.
Bác @giaiphap sao không dùng cái này làm skin mà dùng cách code skin theo kiểu cũ, GetPixel, SetPixel... trên C/C++ còn chạy chậm bỏ cha.
Hàm này và hàm TransparentBlt sau này mới có từ Win2000
Tôi định xác định màu các pixel sau đó dùng hàm CombineRgn để kết hợp các pixel có màu đó và Transparent nó khỏi Form (Dí nhiên chí tốn công một lần sau đó lưu lại thành List trong file text trước khi gọi Form mình đọc các giá trị trong file Text và sử dụng thôi, lúc này tốc độ sẽ nhanh hơn rất nhiều so với đọc từ pixcel trên Form).
 

ilvba

Thành viên mới
Tham gia ngày
24 Tháng sáu 2019
Bài viết
25
Được thích
1
Điểm
15
Tuổi
28
Đẹp quá ạ. Đoạn code nào làm trong suốt userform vậy anh. Nhìn code tùm lum nên em không hiểu mấy ạ.
 

Nguyễn Duy Tuân

Nghị Hách
Thành viên danh dự
Tham gia ngày
13 Tháng sáu 2006
Bài viết
4,080
Được thích
9,532
Điểm
860
Nơi ở
Hà Nội
Đừng dùng màu trắng để cắt hình. Như mình nói phải dùng màu khác là toits nhất. Vấn đề bạn dùng công cụ Photoshop chọn mầu có lỗi gì đó? Có thể bạn đưa bảng màu theo 24-bit Bitmap.
 

batman1

Thành viên gắn bó
Tham gia ngày
8 Tháng chín 2014
Bài viết
1,818
Được thích
2,818
Điểm
360
GetPixel và SetPixel chậm là đúng rồi. Nếu trong Delphi thì ngay Delphi 5 có ScanLine rất nhanh.

Kiểu hoạt hình ABC thì cũng đơn giản. Vd. copy con cá lên màn hình thì cần 2 ảnh: ảnh con cá trên nền đen, ảnh trắng đen - chỗ con cá thì đen, nền trắng. Sau đó dùng 2 BitBlt copy liên tiếp 2 ảnh lên màn hình. Cách này khi animation sẽ hơi nhấp nháy nếu animation con cá "dịch chuyển" (bơi). Loại bỏ nhấp nháy bằng cách: dùng 2 BitBlt copy vào memory device context destDC, sau đó mới 1 BitBlt copy từ destDC vào device context màn hình.

Thay vì con cá có thể là người, xe tăng, cây, viên đạn.

Đấy là ABC chỉ dùng BitBlt. Ngoài ra có DirectX ...

Theo tôi dùng mầu nào cũng được miễn là khác mầu ảnh. Nếu ảnh không có mầu trắng thì dùng mầu trắng làm nền và đường cắt cũng mầu trắng. Lúc này mầu trắng là crKey. Nếu lấy mầu nền, vd. trắng, làm crKey mà nhìn thấy đường viền thì chứng tỏ mầu viền không chính xác 100% bằng mầu nền.
Cái khó là cắt đường viền cho đẹp. Cắt không khéo thì nhì đường viền nhìn lởm chởm, răng cưa không được "mịn".
 
Lần chỉnh sửa cuối:

giaiphap

Thành viên gạo cội
Tham gia ngày
12 Tháng ba 2007
Bài viết
4,676
Được thích
3,860
Điểm
860
GetPixel và SetPixel chậm là đúng rồi. Nếu trong Delphi thì ngay Delphi 5 có ScanLine rất nhanh.

Kiểu hoạt hình ABC thì cũng đơn giản. Vd. copy con cá lên màn hình thì cần 2 ảnh: ảnh con cá trên nền đen, ảnh trắng đen - chỗ con cá thì đen, nền trắng. Sau đó dùng 2 BitBlt copy liên tiếp 2 ảnh lên màn hình. Cách này khi animation sẽ hơi nhấp nháy nếu animation con cá "dịch chuyển" (bơi). Loại bỏ nhấp nháy bằng cách: dùng 2 BitBlt copy vào memory device context destDC, sau đó mới 1 BitBlt copy từ destDC vào device context màn hình.

Thay vì con cá có thể là người, xe tăng, cây, viên đạn.

Đấy là ABC chỉ dùng BitBlt. Ngoài ra có DirectX ...
Anh có thể viết em xem file mẫu được không? Cái phần API em còn gà quá.
Theo tôi dùng mầu nào cũng được miễn là khác mầu ảnh. Nếu ảnh không có mầu trắng thì dùng mầu trắng làm nền và đường cắt cũng mầu trắng. Lúc này mầu trắng là crKey. Nếu lấy mầu nền, vd. trắng, làm crKey mà nhìn thấy đường viền thì chứng tỏ mầu viền không chính xác 100% bằng mầu nền.
Cái khó là cắt đường viền cho đẹp. Cắt không khéo thì nhì đường viền nhìn lởm chởm, răng cưa không được "mịn".
Em thống nhất với anh cái chổ màu đỏ. Khôg biết thế nào, chứ rõ ràng là em chọn vùng và Fill cùng một màu không biết sao nó lại nham nhỡ thế kia.
 

batman1

Thành viên gắn bó
Tham gia ngày
8 Tháng chín 2014
Bài viết
1,818
Được thích
2,818
Điểm
360
Anh có thể viết em xem file mẫu được không? Cái phần API em còn gà quá.
Nhưng bạn muốn biết cái gì? Cái con cá?

Nếu là hoạt hình ở mức ABC như tôi nói thì tôi không có đủ kiên nhẫn để soạn 2 tập tin với con cá nhưng nếu coi 1 hình tròn đỏ là con cá thì như tập tin đính kèm.

Nếu là dịch chuyển con cá - hình tròn đỏ thì các bước như sau:
Ảnh là hình tròn nhưng ảnh bao giờ cũng là hình vuông., giả sử có cạnh = a. Mỗi lần dịch là deltaX, deltaY (pixels)
1. Xác định xStart, yStart
2. Đọc device context của màn hình (GetDC). Tạo memory device context source srcDC (CreateCompatibleDC). Tạo bitmap srcBmp(CreateCompatibleBitmap) có dài và cao = a. Chọn srcBmp vào srcDC -> dùng BitBlt copy màn hình có tọa độ từ xStart, yStart và width = a, height = a vào srcDC. Mục đích để cất giữ ảnh nguồn.
3. Copy liên tiếp 2 ảnh con cá vào xStart, yStart như tôi làm trong tập tin đính kèm trong Sub animation (thay cho 200, 200 thì là xStart, yStart). Con cá đã được copy lên màn hình.
4. Sleep một tí.
5. dùng BitBlt copy từ srcDC vào device context của màn hình (GetDC) vào xStart, yStart để trả lại ảnh của màn hình trước khi copy con cá vào.
6. xStart = xStart + deltaX, yStart = yStart + deltaY
7. Trở lại điểm 2.

Tóm lại chẳng qua là copy liên tiếp con cá lên màn hình ở những điểm khác nhau nhưng giữa 2 lần copy phải trả lại vùng màn hình cũ mà con cá trước đã xóa mất. Để có thể trả lại vùng mà con cá sẽ xóa thì trước khi copy vào đâu thì sao chép nó ra srcDC -> copy con cá -> trả lại vùng đã sao chép -> tăng xStart, yStart -> sao chép vùng ở vị trí mới ra srcDC -> copy con cá vào vị trí mới -> trả lại vùng đã sao chép -> tăng xStart, yStart -> ...

Nôm na là thế. Tất nhiên sau mỗi lần thao tác cần giải phóng resource. Nếu trước đó là GetDC (Get - đọc ra, lấy ra, mượn syatem) thì sau đó ReleaseDC (release - giải phóng, trả lại). Nếu là CreateCompatibleDC, CreateCompatibleBitmap (Create - tạo ra) thì sau đó là DeleteDC, DeleteObject (Delete - hủy) v...v

Get - đọc ra, mượn những cái CÓ trong system -> Release - TRẢ LẠI

Create - tự TẠO RA cái mới -> Delete - HỦY cái đã tạo.

Có mượn có trả, có "thêm rác" (chỉ dùng cho mình) vào system thì có "dọn rác" để system trở về trạng thái như cũ.

Cũng có thể thử tạo srcDC và srcBmp một lần thôi.
-------------
Cách vẽ thứ 2 là chỉ copy 1 hình con cá trên nền bất kỳ lên màn hình nhưng giới hạn vùng copy bằng Region. Trong tập tin tôi tạo region bằng CreateEllipticRgn vì con cá hình tròn. Trong thực tế thì từ đường viền con cá phải tạo region bằng CreatePolygonRgn. Nếu hình phức tạp thì tạo các region rồi dùng CombineRgn để tạo region tổng.
Trong ví dụ nhìn thấy chút viền mầu đen do tôi tạo ảnh trong Paint nhưng đường tròn và hình vuông không 100% đồng tâm.
 

File đính kèm

Lần chỉnh sửa cuối:
Top