65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.37/5 (15投票s)

2002年4月23日

4分钟阅读

viewsIcon

131443

downloadIcon

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);
    }
}
© . All rights reserved.