Dạ xin chào các Anh/ Chị.
Em không biết gửi ở chổ nào nên gửi lên đây.
Cho em hỏi mình có công cụ control nào thay thế image để hiện thị ảnh không ạ, do công cụ này không hiển thị được ảnh có đuôi .png .
Xin cảm ơn,
Dạ xin chào các Anh/ Chị.
Em không biết gửi ở chổ nào nên gửi lên đây.
Cho em hỏi mình có công cụ control nào thay thế image để hiện thị ảnh không ạ, do công cụ này không hiển thị được ảnh có đuôi .png .
Xin cảm ơn,
Hi. I have searched the internet for this solution but keep coming up blank. I have two issues: 1) Is it possible through VBA to allow png files to be inserted as images into a userform. I found some code on another site but didn't really understand how it worked. Not sure allowed to...
Hi. I have searched the internet for this solution but keep coming up blank. I have two issues: 1) Is it possible through VBA to allow png files to be inserted as images into a userform. I found some code on another site but didn't really understand how it worked. Not sure allowed to...
Dạ xin chào các Anh/ Chị.
Em không biết gửi ở chổ nào nên gửi lên đây.
Cho em hỏi mình có công cụ control nào thay thế image để hiện thị ảnh không ạ, do công cụ này không hiển thị được ảnh có đuôi .png .
Xin cảm ơn,
Bạn muốn chèn ảnh có nền trong suốt à?
Dùng BMP cũng được nhưng định dạng này không có nén ảnh nên hơi nặng. Tốt hơn thì chuyển ảnh sang GIF là nhẹ nhất (chỉ có 256 màu - 8 bit). Nếu ảnh chỉ dùng ít màu, ít màu chuyển, ảnh dạng text nhiều...thì nên lưu sang GIF để đưa vào Userform cho nhẹ.
Bổ sung là:
- Đốii với ảnh BMP thì dùng làm icon nút lệnh sẽ có hỗ trợ nền trong suốt (transparent) nhưng khi đưa vào Image control thì vẫn giữ nguyên nền trắng. Vụ này cũng lạ.
- GIF thì làm icon hay dùng trong Image đều hỗ trợ nền trong suốt.
Minh hoạ dùng cùng 1 file ảnh BMP (16 bit màu, hỗ trợ kênh Alpha). Thực chất hàm UDF LoadImage() theo link của bác giaiphap cung cấp là chuyển đổi file PNG sang BMP rồi load lên Userform.
Dung lượng file ảnh: 100 x 100 (px)
- BMP: 34k
- PNG: 23k
- GIF: 16k
Trong mỗi môi trường lập trình thường có control để dùng cho ảnh. Vd. trong VBA có Image, trong Delphi có TImage, trong VB thì là PictureBox. Nhưng nếu lập trình trong API thuần thì khi chỉ cần hiển thị ảnh một cách đơn giản thì cũng có thể dùng control STATIC của system. STATIC có thể dùng với text để thay cho Label, cũng có thể dùng với ảnh để thay cho Image. Cũng là dùng hàm nào đó để đọc, tạo trong memory HBITMAP. Do cần mở PNG nên ta dùng GDI+. Có HBITMAP rồi thì, như tôi đã viết, có thể làm nhiều việc. Việc ta cần ở đây là "dâng" HBITMAP cho STATIC. Thế thôi. Trong tập tin ví dụ tôi lấy các hàm GDI+, bỏ qua OleCreatePictureIndirect, không dùng Image của VBA.
Ảnh được nhập vào STATIC ở kích thước thực. Nếu ta có khung cố định và muốn nhập ảnh vào khung đó thì ta phải tạo hBitmapDest. Thao tác như sau. Ta tạo device context trong memory DC1 (CreateCompatibleDC) rồi chọn hBitmap1 trả về bởi LoadPictureGDI vào device context DC1 (SelectObject), ghi nhớ oldBitmap1 trả về bởi SelectObject. Tiếp theo tạo device context trong memory DC2 (CreateCompatibleDC). Tạo bitmap trong memory hBitmap2 (CreateCompatibleBitmap) với kích thước của STATIC (ảnh khít STATIC) hoặc giữ đúng tỷ lệ 2 chiều của ảnh nguồn (ảnh center trong STATIC), rồi chọn nó vào device context DC2 (SelectObject), ghi nhớ oldBitmap2 trả về bởi SelectObject. Dùng hàm StretchBlt để copy hBitmap1 từ DC1 sang DC2. Tiếp theo chọn lại oldBitmap1 vào DC1 (SelectObject) rồi hủy hBitmap1 do LoadPictureGDI trả về (DeleteObject), hủy device context DC1 (DeleteDC). Cũng chọn oldBitmap2 vào DC2 (SelectObject), rồi hủy DC2 (DeleteDC). Ta không hủy hBitmap2 vì ta sẽ "dâng" nó cho STATIC. Chỉ đến khi đóng Form thì trước khi hủy STATIC thì code sẽ hủy hBitmap2 (DeleteObject).
Không dùng tập tin đính kèm. Hãy thử dùng tập tin trong bài #16.
Trong mỗi môi trường lập trình thường có control để dùng cho ảnh. Vd. trong VBA có Image, trong Delphi có TImage, trong VB thì là PictureBox. Nhưng nếu lập trình trong API thuần thì khi chỉ cần hiển thị ảnh một cách đơn giản thì cũng có thể dùng control STATIC của system. STATIC có thể dùng với text để thay cho Label, cũng có thể dùng với ảnh để thay cho Image. Cũng là dùng hàm nào đó để đọc, tạo trong memory HBITMAP. Do cần mở PNG nên ta dùng GDI+. Có HBITMAP rồi thì, như tôi đã viết, có thể làm nhiều việc. Việc ta cần ở đây là "dâng" HBITMAP cho STATIC. Thế thôi. Trong tập tin ví dụ tôi lấy các hàm GDI+, bỏ qua OleCreatePictureIndirect, không dùng Image của VBA.
Ảnh được nhập vào STATIC ở kích thước thực. Nếu ta có khung cố định và muốn nhập ảnh vào khung đó thì ta phải tạo hBitmapDest. Thao tác như sau. Ta tạo device context trong memory DC1 (CreateCompatibleDC) rồi chọn hBitmap1 trả về bởi LoadPictureGDI vào device context DC1 (SelectObject), ghi nhớ oldBitmap1 trả về bởi SelectObject. Tiếp theo tạo device context trong memory DC2 (CreateCompatibleDC). Tạo bitmap trong memory hBitmap2 (CreateCompatibleBitmap) với kích thước của STATIC (ảnh khít STATIC) hoặc giữ đúng tỷ lệ 2 chiều của ảnh nguồn (ảnh center trong STATIC), rồi chọn nó vào device context DC2 (SelectObject), ghi nhớ oldBitmap2 trả về bởi SelectObject. Dùng hàm StretchBlt để copy hBitmap1 từ DC1 sang DC2. Tiếp theo chọn lại oldBitmap1 vào DC1 (SelectObject) rồi hủy hBitmap1 do LoadPictureGDI trả về (DeleteObject), hủy device context DC1 (DeleteDC). Cũng chọn oldBitmap2 vào DC2 (SelectObject), rồi hủy DC2 (DeleteDC). Ta không hủy hBitmap2 vì ta sẽ "dâng" nó cho STATIC. Chỉ đến khi đóng Form thì trước khi hủy STATIC thì code sẽ hủy hBitmap2 (DeleteObject).
Bạn muốn chèn ảnh có nền trong suốt à?
Dùng BMP cũng được nhưng định dạng này không có nén ảnh nên hơi nặng. Tốt hơn thì chuyển ảnh sang GIF là nhẹ nhất (chỉ có 256 màu - 8 bit). Nếu ảnh chỉ dùng ít màu, ít màu chuyển, ảnh dạng text nhiều...thì nên lưu sang GIF để đưa vào Userform cho nhẹ.
Bổ sung là:
- Đốii với ảnh BMP thì dùng làm icon nút lệnh sẽ có hỗ trợ nền trong suốt (transparent) nhưng khi đưa vào Image control thì vẫn giữ nguyên nền trắng. Vụ này cũng lạ.
- GIF thì làm icon hay dùng trong Image đều hỗ trợ nền trong suốt.
Minh hoạ dùng cùng 1 file ảnh BMP (16 bit màu, hỗ trợ kênh Alpha). Thực chất hàm UDF LoadImage() theo link của bác giaiphap cung cấp là chuyển đổi file PNG sang BMP rồi load lên Userform.
Dung lượng file ảnh: 100 x 100 (px)
- BMP: 34k
- PNG: 23k
- GIF: 16k
Dạ , em đang làm 1 cái forrm đó Anh.
Form em sẽ có . Textbox chứa tên mã hàng. 1 textbox hiển thị thông tin 1 image control để hiển thị ảnh. Và một số thông tin khác. ảnh thì có đuôi .jpg, .png, .bmp
Mà image lại không hiển thị .png được. Nên hỏi các anh chị xem có cách nào không
Cảm ơn Anh.
Hi. I have searched the internet for this solution but keep coming up blank. I have two issues: 1) Is it possible through VBA to allow png files to be inserted as images into a userform. I found some code on another site but didn't really understand how it worked. Not sure allowed to...
Tôi không có office 64 bit nên không thể kiểm tra. Nhưng nhờ rà soát lại code mà tôi phát hiện mấy chỗ không chuẩn - chỉ là khai báo thôi.
1. Type GDIPlusStartupInput chưa được khai báo cho 64 bit
2. SendMessage được khai báo không trước sau như một - cho 64 bit là ByVal lParam As LongPtr, trong khi đó cho 32 bit là ByRef lParam As Any.
3. Private Declare PtrSafe Function FindWindowEx tôi dán vào cả 2 phần mà quên sửa lại cho phần #Else.
4. Private Declare PtrSafe Function GdiplusStartup tôi dán vào cả 2 phần nhưng ở phần #Else chỉ mới sửa các tham số thành Long mà quên không xóa PtrSafe.
Trong tập tin đính kèm tôi đã sửa lại.
Tôi sửa lại, thử không dùng Application.HinstancePtr nữa mà dùng GetWindowLong. Nếu vẫn không được thì thôi chịu, chỉ nhìn chay code thì thấy chả có chỗ nào đáng nghi. LoadPictureGDI và SendMessage tôi cho là không lỗi. Nhất là lỗi kiểu "chết đột ngột". Chả nhẽ Form trong 64 bit khác lạ? Không có 64 bit nên chỉ nhìn thôi.
Bạn giúp tôi test nốt lần này. Vì tôi cũng muốn biết kết quả thế nào. Tôi đã test trên: XP Home 32 bit + Excel 2010 32 bit, Windows 8 32 bit + Excel 2013 32 bit, Windows 10 64 bit + Excel 2007 32 bit đều không có lỗi gì cả. Chỉ có office 64 bit là tôi không có để test.
----------
Tôi nghĩ là bạn chỉ muốn thông báo vấn ̣đề chứ không muốn test. Vì khả năng của bạn thừa để kiểm tra. Hãy biến 3 dòng kể từ dòng
Mã:
If BitmapHandle <> 0 Then DeleteObject BitmapHandle
thành chú thích rồi chạy code. Nếu không có lỗi thì lưu tập tin, đóng tập tin rồi mở lại, rồi mở thêm dòng trên rồi lại chạy code. Nếu không có lỗi thì lưu lại tập tin rồi đóng nó, rồi mở lại. Sau đó lại mở thêm dòng thứ 2. Có tổng cộng 3 dòng thì cùng lắ mở 3 lần. Mỗi lần mở thêm dòng để kiểm tra thì lưu tập tin, đóng và mở lại (do khi chạy không có lỗi thì hStatic <> 0 nên nếu không đóng mà chạy tiếp thì code trong If ... End If không được thực hiện)
Bạn giúp tôi test nốt lần này. Vì tôi cũng muốn biết kết quả thế nào. Tôi đã test trên: XP Home 32 bit + Excel 2010 32 bit, Windows 8 32 bit + Excel 2013 32 bit, Windows 10 64 bit + Excel 2007 32 bit đều không có lỗi gì cả. Chỉ có office 64 bit là tôi không có để test.
Tôi không có office 64 bit nên không thể kiểm tra. Nhưng nhờ rà soát lại code mà tôi phát hiện mấy chỗ không chuẩn - chỉ là khai báo thôi.
1. Type GDIPlusStartupInput chưa được khai báo cho 64 bit
2. SendMessage được khai báo không trước sau như một - cho 64 bit là ByVal lParam As LongPtr, trong khi đó cho 32 bit là ByRef lParam As Any.
3. Private Declare PtrSafe Function FindWindowEx tôi dán vào cả 2 phần mà quên sửa lại cho phần #Else.
4. Private Declare PtrSafe Function GdiplusStartup tôi dán vào cả 2 phần nhưng ở phần #Else chỉ mới sửa các tham số thành Long mà quên không xóa PtrSafe.
Trong tập tin đính kèm tôi đã sửa lại.
Tôi sửa lại, thử không dùng Application.HinstancePtr nữa mà dùng GetWindowLong. Nếu vẫn không được thì thôi chịu, chỉ nhìn chay code thì thấy chả có chỗ nào đáng nghi. LoadPictureGDI và SendMessage tôi cho là không lỗi. Nhất là lỗi kiểu "chết đột ngột". Chả nhẽ Form trong 64 bit khác lạ? Không có 64 bit nên chỉ nhìn thôi.
Bạn giúp tôi test nốt lần này. Vì tôi cũng muốn biết kết quả thế nào. Tôi đã test trên: XP Home 32 bit + Excel 2010 32 bit, Windows 8 32 bit + Excel 2013 32 bit, Windows 10 64 bit + Excel 2007 32 bit đều không có lỗi gì cả. Chỉ có office 64 bit là tôi không có để test.
----------
Tôi nghĩ là bạn chỉ muốn thông báo vấn ̣đề chứ không muốn test. Vì khả năng của bạn thừa để kiểm tra. Hãy biến 3 dòng kể từ dòng
Mã:
If BitmapHandle <> 0 Then DeleteObject BitmapHandle
thành chú thích rồi chạy code. Nếu không có lỗi thì lưu tập tin, đóng tập tin rồi mở lại, rồi mở thêm dòng trên rồi lại chạy code. Nếu không có lỗi thì lưu lại tập tin rồi đóng nó, rồi mở lại. Sau đó lại mở thêm dòng thứ 2. Có tổng cộng 3 dòng thì cùng lắ mở 3 lần. Mỗi lần mở thêm dòng để kiểm tra thì lưu tập tin, đóng và mở lại (do khi chạy không có lỗi thì hStatic <> 0 nên nếu không đóng mà chạy tiếp thì code trong If ... End If không được thực hiện)