具有类似 Java-AWT 源代码的 C++ Win32 GUI 库






4.37/5 (15投票s)
2002年4月23日
4分钟阅读

131443

1295
该库提供了一组简单的类来创建 GUI。它仅使用 Win32 API 和一些常用控件。该开发尚处于早期阶段,还有许多更改要做。
源代码文件包含两个工作区
- jlWindows 本身,生成一个 .lib.
- Testor,以 jlWindows 为依赖.
请访问由 MtpForge 托管的 jlWindows,在此处。
引言
该库的总体目标是提供一个真正易于使用的 GUI API。为简单的软件创建小型 GUI 应该非常快速且整洁,只需几行代码,组件的行为就隔离在类中。
将来,该库可能允许创建远程 GUI,即 new jlWindow("192.168.xx.xx");
或类似的。另一个想法是使 jlWindows
GUI 可动态修改,例如,允许在选项卡之间复制/粘贴按钮或文本字段,并使所有组件可调整大小,甚至可重命名。我还想将其移植到 X。
目前,我正在尝试覆盖原生的 Win32 函数和数据结构,在我看来,这些结构相当混乱。因此 jlWindows
倾向于提供现有 API 的一致视图。然后我想要提供更多功能,例如自动在窗口中组织组件的布局管理器。
该库创建于 2002 年 4 月,但离最终版本还很远。
如今,它允许
- 创建一些基本组件:窗口、按钮、文本字段、列表视图……
- 设置窗口的一些属性,如父窗口、位置、大小、窗口标题……
- 设置一些特定属性,如列表视图的图标集、按钮的标题或图标……
- 通过组件设置一个回调处理程序,它具有一些默认行为。
如何使用它
有两个基类
jlComponent
jlCallbackHandler
组件是可见的元素,例如带标题栏的窗口、按钮和文本字段。每种类型的组件都有一个类,它继承自 jlComponent
(直接或间接)。您可以通过不传递任何参数给构造函数来创建组件,但您也可以传递父窗口和样式(即 Win32 样式)作为参数。创建组件后,您无法再更改其样式。但是,您可以通过调用相应的方法来更改任何其他属性。您甚至可以更改窗口的父窗口,从而将组件从一个位置移动到另一个位置。
您可以给组件一个回调处理程序,它将接收 Win32 消息并对其进行处理。每种类型的组件都有一个关联的回调处理程序类型,因为例如,按钮在被单击时与列表视图的行为不同。您的图形用户界面的每个交互式组件都将拥有一个回调处理程序。您可以使用 jlWindows
的回调处理程序的默认行为,例如 jlWindowCallback
,它在收到 WM_DESTROY
消息时调用 PostQuitMessage()
。但很可能您需要覆盖回调处理程序以赋予您的应用程序所需的行为。
回调处理程序的工作是根据接收到的消息调用(在自身上)特定的方法。它有一个方法,每次关联的组件收到消息时都会被调用。该方法应返回 true
如果消息未被处理,或者更普遍地说,如果您希望调用组件的默认回调函数。
这是 jlTextField
的回调处理程序的调度函数
bool jlTextFieldCallback::componentCallback(HWND WindowHandle,
UINT Message, WPARAM WParam, LPARAM LParam)
{
switch (Message)
{
case WM_DROPFILES:
return filesDropped(WParam);
break;
}
return true;
}
当您覆盖回调处理程序时,您的任务是填写回调处理程序调度函数调用的那些方法,如上例所示,方法 filesDropped()
。
示例
以下代码创建了示例应用程序(其屏幕截图和源代码在上面)
-- main.cpp --
#include <windows.h>
#include <stdio.h>
#include "jlWindows.h"
#include "resource.h"
#include "mytoolbarcallback.h"
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
// jlComponent ( jlComponent * parentcomponent = NULL ,
// DWORD style = 0 , DWORD exstyle = 0 );
jlWindow * win = new jlWindow(NULL, WS_OVERLAPPEDWINDOW);
jlToolbar * tb = new jlToolbar();
win->setTitle("jlWindows Testor");
win->setSize(400,300);
win->show();
// sets a default callback handler for the window
// this callback handler calls PostQuitMessage(0) on WM_DESTROY
win->setCallbackHandler(new jlWindowCallback());
tb->setButtonSize(16, 16);
tb->setImageList(IDB_BITMAP1);
tb->addButtons(2, 0); // addButtons (int count, int start_image)
tb->addButtons(2, 0);
// I created a simple class MyToolbarCallback to handle
// the messages the tb receives. It just pops a messagebox up
// with the zero-based number of the button of the toolbar
tb->setCallbackHandler(new MyToolbarCallback());
// just an example of listview that does nothing
jlListView * lv = new jlListView();
lv->setPosition(30,30);
lv->setSize(200,200);
lv->addColumn("second");
lv->addColumn("third");
lv->setImageList(IDB_BITMAP1);
lv->addItem(0, "blah1"); // addItem (U32 line_index, char * text)
lv->addItem(1, "blah2");
lv->addItem(2, "blah3");
lv->setMasterColumn("first");
win->addToolbar(tb);
win->addComponent(lv);
// receives and dispatches messages to jlWindows Components
// this function returns when the message WM_QUIT
// (sent by PostQuitMessage()) is received
jlComponent::loop();
return 0;
}
-- mytoolbarcallback.h --
#ifndef MYTOOLBARCALLBACK
#define MYTOOLBARCALLBACK
#include <windows.h>
#include "jlWindows.h"
class MyToolbarCallback : public jlToolbarCallback
{
virtual bool buttonClicked(int button_id);
};
#endif // MYTOOLBARCALLBACK
-- mytoolbarcallback.cpp --
#include <windows.h>
#include <stdio.h>
#include "mytoolbarcallback.h"
bool MyToolbarCallback::buttonClicked(int button_id)
{
char msg[10];
sprintf(msg, "%d", button_id);
MessageBox(NULL, msg, "toolbar", MB_OK);
return false;
}
工作原理
每个 jlComponent
都拥有与其关联的 Win32 项(通常称为窗口,无论它是按钮、菜单还是列表视图)的 HANDLE
。创建 jlComponent
时,会调用 CreateWindowEx()
,并使用您在参数中提供的样式和父窗口,或使用默认样式。按钮、列表视图等使用预定义的窗口类,并带有预定义的回调函数,使它们表现正常。但在创建后,窗口会被赋予一个新的回调函数,即 jlWindows
的回调函数,该函数对每个 jlComponent
都是通用的。窗口还会被赋予特定的“用户数据”。每个窗口都将一个指向与之关联的 jlComponent
的指针作为用户数据接收。这些属性通过调用 SetWindowLong()
来设置。然后,在 jlWindows
的全局回调函数中,从接收到消息的窗口中检索用户数据。这样,jlWindows
就知道消息要发送给哪个 jlComponent
。它只需在其上调用一个方法,该 jlComponent
就会将其消息转发给它的回调处理程序(如果有)。
请注意,如果 jlWindows
的全局回调函数检测到 jlComponent
未处理消息,它会调用与之关联的窗口的标准回调函数,该函数在设置 jlWindows
的回调函数时已被保存。大多数情况下,应该让 jlWindows
调用组件的标准回调函数,因为它通常会处理其显示。例如,覆盖按钮被单击时的行为而不让 jlWindows
调用其标准回调函数,将会阻止它显示为按下状态。
创建组件、设置其属性、回调处理程序并显示它们后,您必须调用 jlComponent::loop();
。该静态方法将接收并调度您设计的图形界面接收的消息。该方法的代码在每个 C++/Win32 应用程序中都是典型的,并且始终相同。该循环仅在接收到 WM_QUIT
消息时结束
void jlComponent::loop()
{
MSG Message;
int Status;
while ((Status = GetMessage(&Message, NULL, 0, 0)))
{
if (Status == -1)
break;
TranslateMessage(&Message);
DispatchMessage(&Message);
}
}