8 điểm bởi GN⁺ 2024-07-01 | 7 bình luận | Chia sẻ qua WhatsApp
  • Tổng hợp kết quả tìm kiếm và so sánh các thư viện để viết GUI bằng C++
  • Yêu cầu cơ bản: chỉ cần hỗ trợ Windows, cho phép sử dụng thương mại, dễ tùy biến giao diện kèm dark mode, tạo một file EXE duy nhất dưới 40MB với ít phụ thuộc nhất, phát triển nhanh

WinUI 3

  • Ban đầu có vẻ là một lựa chọn tuyệt vời
  • Có thể sử dụng các thành phần Windows hiện đại và tùy biến màu sắc giao diện
  • Có thể thiết kế bằng XAML và thậm chí dùng trực tiếp Visual Studio Designer
  • Vấn đề:
    • Việc phân phối ứng dụng ở dạng không đóng gói không được hỗ trợ tốt
    • Khi chuyển ứng dụng sang VM hoặc máy tính khác thì phần lớn đều không chạy được
    • Phải kèm theo rất nhiều file .dll để xử lý các tính năng của WinUI
    • Không thể tạo một file .exe portable duy nhất
    • Dùng ở dạng package thì không sao, nhưng sẽ được cài dưới dạng gói AppX nên phát sinh vấn đề truy cập Win32 API

Win32 / MFC / các thư viện nhỏ bọc Win32

  • Vì cần tính di động cao nên việc dùng cơ chế render gốc của hệ điều hành là hợp lý
  • Chương trình có thể là một file .exe duy nhất và kích thước cũng có thể rất nhỏ (nếu liên kết tĩnh MFC)
  • Có thể dùng một thư viện tối giản hơn do người khác đã viết sẵn
  • Vấn đề:
    • Việc tạo kiểu cho các control Win32 mặc định là rất khó
    • Phải tự viết chức năng custom paint cho mọi control
    • Có dark mode “ẩn” dùng trong Windows File Explorer, nhưng chỉ áp dụng cho một số control và nhìn vẫn không ổn

Qt

  • Chén thánh của GUI C++
  • Phức tạp nhưng có thể tạo kiểu dễ dàng bằng Qt Style Sheets
  • Vấn đề:
    • Khi liên kết động thì cần vô số file .dll để chạy ứng dụng và tổng kích thước vượt quá 40MB
    • Có thể liên kết tĩnh Qt vào chương trình, nhưng khi đó phải mở mã nguồn hoặc phân phối các object file để người dùng biên dịch lại do giấy phép LGPL của Qt
    • Hoặc có thể mua giấy phép thương mại, nhưng giá lên tới hàng nghìn đô

wxWidgets

  • Thư viện dễ học
  • Có thể dùng wxFormBuilder
  • Có giấy phép dễ chịu hơn Qt và có thể liên kết tĩnh thành file thực thi 3MB
  • Vấn đề:
    • Trên Windows, nó dùng các thành phần Win32 mặc định và không cung cấp nhiều tùy chọn styling
    • Có hỗ trợ áp dụng dark control của Windows File Explorer nhưng kết quả không mấy tốt

hikogui

  • Thư viện GUI retained mode mới dùng Vulkan làm backend
  • Có sẵn dark mode và dễ tạo kiểu
  • Vấn đề:
    • Muốn biên dịch thành công có lẽ phải có bằng tiến sĩ khoa học máy tính
    • Sau hơn 30 phút cố biên dịch ví dụ, kết quả duy nhất nhận được là file thực thi bị crash ngay lập tức với lỗi access violation bên trong thư viện Vulkan

Sciter

  • Một lựa chọn thay thế tốt cho Electron, cho phép viết GUI cho ứng dụng desktop bằng HTML/CSS
  • Vấn đề:
    • Ứng dụng cuối cùng có kích thước khoảng 25MB kèm toàn bộ .dll, đây có thể là vấn đề nhưng vẫn chấp nhận được
    • Sẽ tốt hơn nếu nó là mã nguồn mở và có phiên bản liên kết tĩnh cho mục đích thương mại
    • Không đắt như Qt ($310), nên trả tiền cũng thấy vui vẻ
    • Vấn đề là chất lượng render không thật sự tốt
    • Gặp vấn đề aliasing với font và hình ảnh
    • Cửa sổ có một khung viền xám khá dày (2-3px) mà không thể tùy biến hay chỉnh sửa

WinForms / WPF

  • Khi hỏi về thư viện GUI cho C++, đa số mọi người lại khuyên dùng stack khác
    • Họ nói C++ là một ý tưởng tồi, nên hãy viết frontend của chương trình bằng stack khác và nạp phần chức năng viết bằng C++ dưới dạng component/module
  • Có thể có một file .exe duy nhất với kích thước nhỏ và dùng WinForms/WPF
  • Có thể bundle các file .dll làm resource trong ứng dụng, giải nén ra thư mục tạm rồi dùng P/Invoke để gọi .dll đã biên dịch từ trong ứng dụng C#/.NET, hoặc dùng C++/CLI
  • Vấn đề:
    • .NET Framework được cài sẵn trên Windows 10 trở lên, nên về mặt kỹ thuật có thể xem là đáp ứng tiêu chí không phụ thuộc
      • Nếu bundle .dll thì vẫn phải giải nén chúng ra đâu đó và cần viết thêm mã để P/Invoke hoạt động
      • C++/CLI sẽ được biên dịch thành mã .NET IL, tức là nhìn như mã C++ đã được “dịch” sang C#

Giải pháp?

  • Với các ứng dụng đơn giản, có lẽ không gì phù hợp hơn Dear ImGui
  • Khi thiết kế UI phức tạp thì nó chủ yếu bộc lộ nhược điểm, và vì là immediate mode UI chứ không phải retained mode UI nên phải chạy renderer GPU như DirectX để render UI ở 60 khung hình/giây trở lên
  • Tuy nhiên ở mọi khía cạnh khác thì nó lại rất khớp với nhu cầu
  • Chương trình sau khi biên dịch chỉ nặng 500KB và không cần cài VC++ Redistributable

Ý kiến của GN⁺

  • Có vẻ như đúng như tác giả nói, không tồn tại thư viện hoàn hảo cho việc phát triển ứng dụng GUI. Tùy vào yêu cầu mà sẽ phải đánh đổi
  • Với các ứng dụng đơn giản, Dear ImGui có vẻ phù hợp nhất, nhưng nếu cần làm UI phức tạp thì dùng bộ công cụ GUI retained mode sẽ tốt hơn
  • Nếu làm ứng dụng thương mại thì chi phí giấy phép có thể là yếu tố quan trọng. Các thư viện như Qt có chi phí cao, trong khi wxWidgets có thể dùng miễn phí
  • Việc tạo ứng dụng GUI bằng C++ không phải chuyện dễ, nên thực tế hơn có thể là phát triển frontend bằng C# hoặc ngôn ngữ khác, còn chỉ triển khai phần đòi hỏi hiệu năng bằng C++
  • Nếu muốn giao diện native look-and-feel trên Windows thì WinUI hoặc MFC là lựa chọn tốt, còn nếu cần hỗ trợ đa nền tảng thì Qt hoặc wxWidgets có thể phù hợp hơn

7 bình luận

 
tsboard 2024-07-05

hikogui đúng là đáng sợ thật run run run

 
fastkoder 2024-07-03

https://getstream.io/blog/flutter-desktop-vs-electron/ So sánh hiệu năng theo nhiều chỉ số khác nhau

 
fastkoder 2024-07-03

So với Sciter và Electron, Flutter Windows Desktop Build cũng là một lựa chọn đáng cân nhắc. Thỉnh thoảng có một số plugin bị lỗi, nhưng nền tảng cơ bản khá vững nên có thể dùng như một phương tiện triển khai.
Singleton instance, tự động cập nhật, thanh trạng thái, thông báo Windows, thời gian khởi chạy nhanh, ngôn ngữ Dart, plugin Win32API, v.v.

 
soone 2024-07-03

Delphi

 
soone 2024-07-03

C++ Builder

 
joyfui 2024-07-02

"Cần có bằng tiến sĩ khoa học máy tính mới biên dịch thành công"
haha

 
GN⁺ 2024-07-01
Ý kiến Hacker News
  • Sau khi đọc nhiều bình luận, tôi nhận ra tiền đề tổng thể đã sai. Có lẽ nên đổi tên bài blog thành "Viết ứng dụng GUI cho Windows thật đau khổ khi các yêu cầu phi thực tế"
  • Nên nhắm mục tiêu WinForms bằng .NET Framework 3.5. Nó đã được cài trên mọi phiên bản Windows hiện đại
  • Bài viết này cung cấp cái nhìn tổng quan tốt về nhiều lựa chọn, nhưng các yêu cầu cụ thể của tác giả đã loại trừ nhiều phương án
    • Yêu cầu muốn kiểu dáng GUI được tùy biến hoàn toàn nhưng lại không muốn tự viết các hàm render riêng khiến bài toán trở thành việc chọn một thư viện GUI dễ tùy biến
    • Yêu cầu tệp thực thi tự chứa cùng giới hạn kích thước dưới 40MB cũng loại bỏ nhiều lựa chọn. Qt có thể đáp ứng các yêu cầu này, nhưng giấy phép mã nguồn mở của nó không phù hợp với mục tiêu và tác giả không muốn mua giấy phép
    • Nếu chấp nhận phụ thuộc, hoặc chấp nhận kích thước tải xuống lớn hơn, hoặc dùng các control GUI tích hợp của Windows, thì tình hình sẽ rất khác
    • Nếu muốn viết một GUI hoàn toàn tùy biến, nhẹ, không phụ thuộc bên ngoài và cần giấy phép dễ dãi, tôi đã nghĩ ImGui sẽ là câu trả lời
  • Chỉ ra rằng ý tưởng WinForms/WPF không có khuyết điểm lớn nào, nhưng ngoài việc đòi hỏi hai stack thì không nói thêm gì. Tác giả muốn mã native và không muốn thấy C#, nhưng không giải thích lý do. Có thể là vì sợ bị dịch ngược. Mã UI hiếm khi chứa bí mật
    • Triển khai dưới dạng một file exe đôi khi tiện, nhưng trong kịch bản này có thể khá phiền. Dùng trình đóng gói như Velopack (Squirrel) có thể phân phối dưới dạng một file exe và còn thêm cả tính năng tự động cập nhật. Việc có từ hai tệp trở lên trên đĩa sau khi cài đặt là một sự thỏa hiệp hợp lý
    • Windows, khi loại trừ mọi nền tảng khác, là nền tảng tệ nhất để phát triển ứng dụng desktop
  • Tôi có đánh giá rất thấp về các lập trình viên chỉ trích việc phải trả phí giấy phép thương mại cho các thư viện phần mềm theo giấy phép LGPL. Họ kỳ vọng được đền đáp cho công việc của mình và đảm bảo điều đó bằng cách tạo ra phần mềm mã nguồn đóng. Nhưng các lập trình viên đã giải quyết phần khó thực sự của việc làm thư viện UI thì lại phải trở thành những người trưởng thành, miễn phí tặng mã của mình cho cả thế giới
  • Về Sciter và vấn đề "khử răng cưa"... tác giả đã không bật hỗ trợ DPI độ phân giải cao trong ứng dụng
    • Có thể khắc phục bằng cách bật trong Visual Studio hoặc thêm manifest phù hợp
    • Điều này được giải thích trong hướng dẫn "Hello C++"
  • Nói chính xác hơn:
    • "Portable" (một file exe duy nhất, không tự giải nén)
    • Mang tính thương mại và không muốn phân phối lại các file đối tượng đã biên dịch (điều này, kết hợp với yêu cầu "portable", khiến LGPL không thể chấp nhận)
    • Chế độ tối
    • Ứng dụng GUI Windows thì đau khổ. Bỏ đi một trong các yêu cầu này thì sẽ có nhiều lựa chọn tốt
    • Hầu hết ứng dụng "portable" dùng win32. Thông thường, ứng dụng portable là những ứng dụng nhỏ và đơn giản, nơi chức năng quan trọng hơn dark mode hay các khả năng tạo kiểu khác
  • Là người đòi hỏi nhiều từ mã nguồn mở của người khác, tác giả lại không định công khai giải pháp của mình dưới dạng mã nguồn mở
  • Tôi đang làm một bộ công cụ GUI phù hợp với các yêu cầu đó: Slint - https://slint.dev
    • Có thể được biên dịch tĩnh thành một file .exe duy nhất và có kích thước dưới 40M. Có giấy phép cho phép dùng miễn phí trên desktop. Cung cấp giao diện tối/sáng. Còn bao gồm cả trình biên tập WYSIWYG kéo-thả (đang được phát triển)
  • Việc phải tự viết hàm vẽ tùy chỉnh cho mọi control cho thấy triết lý win32 cũ không phù hợp với tác giả. Yếu tố cốt lõi của win32 là wndproc. Phần lớn các control sẽ hỏi màu từ control cha
    • Nếu thấy bất tiện, bọc nó bằng một thư viện nhỏ để loại bỏ boilerplate không phải là vấn đề lớn
  • Kết quả phải là một file .exe duy nhất, không có phụ thuộc hoặc chỉ có phụ thuộc tối thiểu, và nhỏ hơn 40MB
    • Máy tính ngày nay đã có trình duyệt hiện đại. Thay vì file .exe, có thể dùng một file .html duy nhất với image/css/javascript được nhúng inline