我刚刚开始在 Mac System 7.5.5 中使用MetroWerks CodeWarrior 1.1 For Mac 68k,但我需要知道:如何创建一个带有 TextBox 的简单表单?谢谢。
2 回答
我不知道 CodeWarrior 1.1 是否包含 GUI 设计器,但您可以使用本机 C-API (CreateNewWindow) 创建一个窗口。
问题是,不再有 7.5 的在线文档,所以我无法详细帮助您。
有几种方法可以做到这一点。如果你的 CodeWarrior 版本有它,你最好使用 PowerPlant 框架。这是一个应用程序框架,可以相对轻松地构建遵循 Mac UI 标准的应用程序。已经 10 多年了,所以我已经从记忆中完全清除了 PowerPlant 类层次结构。对不起。
另一种方法是在 ResEdit 中创建一个 DLOG 资源,其中包括一个或多或少适合窗口的 TextEdit 字段。然后你编写你的主应用程序,它将包括典型的工具箱初始化(我完全是从内存中完成的):
DialogPtr myDlog;
short itemHit;
InitGraf( &qd.thePort );
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs( 0L );
InitCursor();
myDlog = GetNewDialog(myDlogResID, 0L, -1L);
ShowWindow(myDlog);
while (true) {
ModalDialog(myDlog, &itemHit);
}
这可能会起作用,并且是在 Mac 上做 UI 的最错误的方式,但如果你想要的只是一个带有简单 UI 的盒子,你会没事的。
这段代码的问题是它不能很好地处理事件,循环是无限的,没有处理剪切/复制/粘贴,没有处理菜单事件等等。
那个时代的 Mac 工具箱需要你做的工作比你想象的要多得多。这就是为什么有像 MacApp、Think Class Library 和 PowerPlant 这样的库的原因——它们提供了 OOP 方法来为你处理很多家务琐事。在我进行大部分 Mac 编程时,我构建了一个非类库,它是原始 C 代码,可以更轻松地编写分层窗口(带有浮动调色板)和流畅的 UI,而无需 OOP 开销。基本上,我必须编写一个窗口管理器、一个菜单管理器、一个对话框管理器、一个事件管理器、一个命令调度程序等等。一切都说完了,构建一个典型的应用程序需要大约 18K 的开销。仅供参考,Macintosh 上的 Acrobat Search 直到第 4 版都基于此构建,Acrobat Catalog 也是如此。
你可以在 MacTech 中找到典型的例子,就像上面的代码一样。
在开始使用对话框构建整个 UI 之前,所有旧的 Macintosh 技术说明都说不要这样做。DialogManager 是有史以来被滥用最多的 Macintosh 代码块之一。它的目的是为了方便放置一个盒子,上面写着“你确定要关闭‘Untitled’吗?” 带有一个确定按钮和一个取消按钮。令人惊讶的是它可以被滥用多少。
做事的真正方法是编写一个初始化工具箱项目的主程序,构建一个基本菜单栏,然后分配一个您设计的对象,比如 NathanWindow。NathanWindow 可能如下所示:
class NathanWindow {
public:
NathanWindow();
virtual ~NathanWindow();
void Initialize();
void Click(short part, EventRecord *evt);
void Show();
void Hide();
void Drag();
void Move();
// etc;
protected:
virtual WindowPtr MakeWindow() = 0;
virtual void OnInit() = 0;
private:
WindowPtr _win;
};
然后您将使用代码对其进行子类化,以适当的样式调用 NewWindow()。
初始化将如下所示:
void NathanWindow::Initialize()
{
_win = MakeWindow();
_win->refCon = this;
OnInit();
}
现在,这最后一点是棘手的部分——我已将指向 NathanWindow 的指针放入 Macintosh WindowPtr refCon 字段。然后,您将在主代码中构建一个事件循环,如下所示:
void HandleMouseDown(EventRecord *evt)
{
WindowPtr win;
short thePart;
thePart = FindWindow( eventPtr->where, &win );
if (win) {
NathanWindow *nw = (NathanWindow *)win->refCon;
nw->Click(thePart, evt);
}
}
void EventLoop( void )
{
EventRecord evt;
while ( true ) {
if ( WaitNextEvent( everyEvent, &evt, kSleep, nil ) ) {
switch (evt.what) {
case mouseDown:
HandleMouseDown(&evt);
break;
}
}
}
然后单击将如下所示:
NathanWindow::Click(short thePart, EventRecord *evt)
{
switch(thePart) {
case inGoAway: Close(); break;
case inDrag: Drag(); break;
case inGrow: Grow(); break;
}
}
等等。
即便如此,这(可能)是错误的,因为您真的希望每个 NathanWindow 都连接到管理窗口层和分组的应用程序父级。
NathanWindow 应包含 NathanControls 的列表。NathanControl 是可以绘制、响应事件等的东西。
所有这一切都是为了以防您没有 PowerPlant,它会为您完成所有这些工作。Apple 喜欢吹捧“这很难容易”这句话是有原因的,因为触手可及的 API 太原始了。