//board.h
#ifndef __BOARD_H__
#define __BOARD_H__
#include "..\SexyAppFramework\Widget.h"
#include "..\SexyAppFramework\ButtonListener.h"
#include "..\SexyAppFramework\Rect.h"
namespace Sexy
{
class V12DemoApp;
class DemoWidget;
class ButtonWidget;
class Board : public Widget, public ButtonListener
{
public:
V12DemoApp* mApp;
private:
// 我们将使用门帘效果. 用下边几个常量表示门帘的几种状态.
enum
{
CURTAIN_CLOSING,
CURTAIN_OPENING,
CURTAIN_INACTIVE
};
DemoWidget* mDemoWidget;
ButtonWidget* mDemoButton; // Creates our DemoWidget
ButtonWidget* mDialogButton; // Creates a little dialog box
ButtonWidget* mCurtainButton; // Initiates the curtain closing/opening transition
Rect mRect; // 不断变化大小的矩形
bool mExpanding; // 矩形在放大还是缩小?
bool mLostFocus; // 程序是否失去了焦点? 在本例子中失去焦点后程序做另一些事情.
int mCurtainMode; // 前边定义的enum中的某一个状态.
int mCurtainWidth; // 记录门帘的宽. 其变化范围在 0 到 宽/2 .
int mDeferPriority; // See the .cpp for full info, but we'll be toggling the overlay priority every second
int mMsgX, mMsgY; // 每秒都移动一下 "LOST FOCUS" 文字. (当窗口失去焦点时. 该文字才显示出来).
public:
Board(V12DemoApp* theApp);
virtual ~Board();
void Update();
void Draw(Graphics* g);
void ButtonDepress(int id);
//
// 在最上层绘制. 它将把图像绘制在所有的控件之上.
// 无论何时你需要这种绘制. 你只需在 Draw() 中调用 DeferOverlay() 函数就可以了 .
// 调用 DeferOverlay()时可以指定一个优先级. 优先级越高就越显示到最上层.
// 可以通过设置优先级来使这种顶层绘制遮住一部分部件. 而不会遮住优先级更高的部件(例如一个设置对话框).
void DrawOverlay(Graphics* g);
void SetFocusLost(bool f) {mLostFocus = f; mDeferPriority = 2;}
};
}
#endif //__BOARD_H__
//demowiget.h
#ifndef __DEMO_WIDGET_H__
#define __DEMO_WIDGET_H__
#include "SexyAppFramework/Widget.h"
#include "SexyAppFramework/ButtonListener.h"
namespace Sexy
{
class ButtonWidget;
class DemoWidget : public Widget, public ButtonListener
{
private:
ButtonWidget* mMoveButton;
ButtonWidget* mCloseButton;
public:
DemoWidget();
virtual ~DemoWidget();
void Draw(Graphics* g);
void ButtonDepress(int id);
};
}
#endif //__DEMO_WIDGET_H__
// v12Demo.h
#ifndef __V12DEMOAPP_H__
#define __V12DEMOAPP_H__
#include "..\SexyAppFramework\SexyAppBase.h"
namespace Sexy
{
class Board;
class V12DemoApp : public SexyAppBase
{
public:
Board* mBoard;
public:
V12DemoApp();
virtual ~V12DemoApp();
//
// Function: ShutdownHook
// 它被基类的 Shutdown() 函数自动调用. 所以这里可以放一些需要在程序关闭时执行的动作. 如释放资源等等.
virtual void ShutdownHook();
//
// 不再需要重载基类的 Init() 函数. 而应该把一些需要初始化时做的工作放在这里(例如载入资源).
// 它会在调用基类的 Init() 函数时被自动执行.
virtual void InitHook();
// 这两个函数可以使程序在获得焦点/失去焦点时做些事情.
virtual void LostFocus();
virtual void GotFocus();
//
// 以前的例子中. 对话框的按钮的"按下/弹起"事件总是发送到 ButtonListener. 处理起来比较麻烦.
// 现在 则只要在 app 类的 DialogButtonDepress / DialogButtonPress 函数中检查
// 指定的 对话框ID 和 按钮ID. 然后指定一个动作执行之.
virtual void DialogButtonDepress(int dialog_id, int button_id);
};
}
#endif //__V12DEMOAPP_H__
//board.cpp
#include "Board.h"
#include "DemoWidget.h"
#include "Res.h"
#include "V12DemoApp.h"
#include "..\SexyAppFramework\Font.h"
#include "..\SexyAppFramework\Graphics.h"
#include "..\SexyAppFramework\ButtonWidget.h"
#include "..\SexyAppFramework\WidgetManager.h"
#include "..\SexyAppFramework\Dialog.h"
#include "..\SexyAppFramework\Flags.h"
#include "..\SexyAppFramework\SexyMatrix.h"
#include "..\SexyAppFramework\trivertex.h"
using namespace Sexy;
Board::Board(V12DemoApp* theApp)
{
mApp = theApp;
// 这里演示如何用部件的 flag system 来设置部件的一些特征. 如是否总是在每帧都重绘. 是否允许鼠标事件等等...
// 它通过设置一些 flag 来指定 widget 这些特征. widget缺省被设置的旗标有:
// WIDGETFLAGS_UPDATE - 允许调用其 Update() 函数.
// WIDGETFLAGS_DRAW - 允许调用其 Draw() 函数.
// WIDGETFLAGS_CLIP - 绘制的图像都剪裁到部件的区域之内(不能在区域之外绘制).
// WIDGETFLAGS_ALLOW_MOUSE - 允许鼠标操作.
// WIDGETFLAGS_ALLOW_FOCUS - 允许处理焦点事件.
// 以前. 为了让部件在每次 Update() 时都绘制一次. 我们在Update()中调用 MarkDirty().
// 现在有另一个办法. 即使用窗体部件的 flag system. 例如下边的例子中. 我们设置 WIDGETFLAGS_MARK_DIRTY 旗标.
// 这样当我们将该 widget 放入部件管理器时. 部件管理器就知道我们想要它在每帧都重画.
mWidgetFlagsMod.mAddFlags |= WIDGETFLAGS_MARK_DIRTY;
// 如上例所示. 要设置一个旗标用 "mWidgetFlagsMod.mAddFlags |= 标志" .
// 而要取消某个旗标则用 "mWidgetFlagsMod.mRemoveFlags |= 标志" 的形式.
// 你也可以修改所有部件的缺省特征. 这需要修改 mApp->mWidgetManager 的 mWidgetFlags.
// 以前, 要把一个 widget 做为子窗口插入另一个 widget 是很烦人的.
// 所以以前的例子中你必须重写 AddedToManager/RemovedFromManager 函数....等等...
// 现在可以直接在父部件的构造函数中创建子部件. 可以用成员函数 AddWidget() 将子部件插入.
// 而且. 在父部件的析够函数中. 也只要在 delete 子部件前加上一句 RemoveAllWidgets() 就可以方便的从部件管理器中移除所有子部件了.
// 创建3个按钮子部件.
mDemoButton = new ButtonWidget(0, this);
mDemoButton->mLabel = _S("Demo Widget");
mDemoButton->SetFont(FONT_DEFAULT);
mDemoButton->Resize(10, 10, 10 + FONT_DEFAULT->StringWidth(mDemoButton->mLabel), 50);
AddWidget(mDemoButton);
mDialogButton = new ButtonWidget(1, this);
mDialogButton->mLabel = _S("Do Dialog");
mDialogButton->SetFont(FONT_DEFAULT);
int w = FONT_DEFAULT->StringWidth(mDialogButton->mLabel);
mDialogButton->Resize(mApp->mWidth - 20 - w, 10, w + 10, 50);
AddWidget(mDialogButton);
mCurtainButton = new ButtonWidget(2, this);
mCurtainButton->mLabel = _S("Do Transition");
mCurtainButton->SetFont(FONT_DEFAULT);
w = FONT_DEFAULT->StringWidth(mCurtainButton->mLabel);
mCurtainButton->Resize(mDemoButton->mX + 20 + mDemoButton->mWidth, 10, w + 10, 50);
AddWidget(mCurtainButton);
mDemoWidget = NULL;
mRect = Rect(mApp->mWidth / 2 - 1, mApp->mHeight / 2 - 1, 2, 2);
mExpanding = true;
mMsgX = Rand() % (mApp->mWidth - 100);
mMsgY = Rand() % (mApp->mHeight - 100);
mLostFocus = false;
mCurtainWidth = 0;
mCurtainMode = CURTAIN_INACTIVE;
// We'll toggle this between 0 and 2 every second when we are unfocussed
mDeferPriority = 0;
}
Board::~Board()
{
// 必须在delete子部件之前调用如下函数. 它可以移除所有子部件.
// 它会将所有的子部件从部件管理器中移除.
RemoveAllWidgets();
delete mDemoButton;
delete mDialogButton;
delete mCurtainButton;
// mDemoWidget 它没有被设置为Board的子部件. 所以上边的 RemoveAllWidgets() 没有移除它.
// 所以需要手动移除.
if (mDemoWidget != NULL)
mApp->mWidgetManager->RemoveWidget(mDemoWidget);
delete mDemoWidget;
}
void Board::Update()
{
Widget::Update();
if (mLostFocus)
{
if (mUpdateCnt % 100 == 0)
{
mMsgX = Rand() % (mApp->mWidth - 100);
mMsgY = Rand() % (mApp->mHeight - 100);
// Every second, we switch between drawing the overlay above or below
// the mDemoWidget object (assuming of course you have the widget on screen
// when you lose focus).
mDeferPriority = mDeferPriority == 0 ? 2 : 0;
}
}
else
{
// This just makes the rectangle in the middle grow/shrink. Nothing
// too crazy.
if (mExpanding)
{
mRect.mWidth += 2;
mRect.mHeight += 2;
if (mRect.mWidth >= mApp->mWidth)
{
mRect.mWidth = mApp->mWidth;
mExpanding = false;
}
if (mRect.mHeight >= mApp->mHeight)
{
mRect.mHeight = mApp->mHeight;
mExpanding = false;
}
}
else
{
mRect.mWidth -= 2;
mRect.mHeight -= 2;
if (mRect.mHeight <= 0)
{
mRect.mHeight = 0;
mExpanding = true;
}
if (mRect.mWidth <= 0)
{
mRect.mWidth = 0;
mExpanding = true;
}
}
mRect.mX = mApp->mWidth / 2 - mRect.mWidth / 2;
mRect.mY = mApp->mHeight / 2 - mRect.mHeight / 2;
}
}
void Board::Draw(Graphics* g)
{
g->SetColor(Color::Black);
g->FillRect(0, 0, mWidth, mHeight);
// Draw our pulsing rectangle in the middle of the screen.
g->SetColor(Color(255, 0, 0));
g->FillRect(mRect);
if (!mLostFocus)
{
// GraphicsAutoState 对象的用法就像 互斥器中的"守卫".
// 它的构造函数执行 g->PushState() 而析够函数执行 g->PopState() .
GraphicsAutoState auto_state(g);
g->DrawImage(IMAGE_HUNGARR_LOGO, 10, 100);
g->SetDrawMode(Graphics::DRAWMODE_ADDITIVE);
g->SetColorizeImages(true);
g->SetColor(Color(mUpdateCnt % 128, mUpdateCnt % 255, mUpdateCnt % 64));
g->DrawImage(IMAGE_HUNGARR_LOGO, 10, 100);
}
if (mCurtainMode != CURTAIN_INACTIVE)
{
g->SetColor(Color(255, 255, 0));
g->FillRect(0, 0, mCurtainWidth, mHeight);
g->FillRect(mWidth - mCurtainWidth, 0, mCurtainWidth, mHeight);
}
// 本例子中. 当失去焦点的时候. 我们在顶层(即所有子部件之上)绘制一些东西.
// DeferOverlay() 的说明见本例子的 Board::DrawOverlay() 函数的声明处.
if (mLostFocus)
DeferOverlay(mDeferPriority);
}
// 在顶层绘制
void Board::DrawOverlay(Graphics* g)
{
g->SetColor(Color(0, 0, 255, 175));
g->FillRect(0, 0, mWidth, mHeight);
g->SetFont(FONT_DEFAULT);
g->SetColor(Color::White);
g->DrawString(_S("LOST FOCUS"), mMsgX, mMsgY);
// 调用下边的 PushState() 函数可以方便的保存 Graphics 对象的当前状态. 以便以后用 PopState() 恢复该状态.
// (当调用 SetColor(), SetDrawMode() 等函数时都会改变 Graphics 对象的状态).
g->PushState();
// 对比在第3个例子中. 有些状态设置后必须在不用的时候改回来(例如平滑拉伸等).
// 现在不用改回来了. 只要在不用的时候一个 g->PopState(); 就返回以前的状态了.
g->SetColorizeImages(true);
g->SetColor(Color(0, 255, 255));
// 在以前的例子中. 我们也对图像做过 缩放/旋转/镜像 绘制. 但那种办法很麻烦.
// 现在我们学习一种新的方法. 它使用一个转换器. 将要对图像做的操作都设置到转换器中.
// 然后绘制时使用 g->DrawImageTransform() 来绘制. 就可以得到想要的效果.
// 转换器对象
Transform t;
// 指定转换器的旋转角度. 参数为需要旋转的角度数(0-360).
t.RotateDeg((float)(mUpdateCnt % 360));
// 根据 Update次数来计算缩放的比例.
// x方向和y方向有各自的比例. 其值为 1.0 表示不缩放.
// 若某个方向的缩放比例为负数. 则表示使用镜像(即左右颠倒或上下颠倒).
float sw;
float sh;
int mod = mUpdateCnt % 200;
if (mod < 100)
{
sw = (float)(mod + 1) / 100.0f;
sh = (float)(mod + 1) / 100.0f;
}
else
{
mod = 200 - mod;
sw = (float)mod / 100.0f;
sh = (float)mod / 100.0f;
}
// 指定 transform 对象的缩放比例.
// 这里我们指定为负数. 即镜像图像.
t.Scale(-sw, -sh);
// 现在绘制图像.
// 通过g->DrawImageTransform/F(). 它的参数分别为:
// 要绘制的图像.
// 转换器.
// x , y 坐标
// 它在2D或3D模式中都可以工作. (这里的x,y坐标是目的图像的中心点吗?)
if (gSexyAppBase->Is3DAccelerated())
g->DrawImageTransformF(IMAGE_HUNGARR_LOGO, t, (float)(mUpdateCnt % (mApp->mWidth + 340)), 200.0f);
else
g->DrawImageTransform(IMAGE_HUNGARR_LOGO, t, (float)(mUpdateCnt % (mApp->mWidth + 340)), 200.0f);
//恢复到调用g->PushState();之前的状态.
g->PopState();
// 下边讲的什么东西不懂.
// You can now draw using matrices. Why the heck would you want to use matrices? Besides doing some
// crazy stuff, you can also do some cool little tricks. For example, previously it used be a pain
// to in real-time flip and mirror an image. While I won't give a tutorial on matrix algebra
// (that would take a loooooong time), I'll explain the essential parts:
SexyTransform2D matrix;
// Multiplying the X coordinate by -1 (which is the 0, 0 element of the matrix) will result in our
// image being mirrored, while multiplying the Y coordinate by -1 (1, 1 in the matrix) will result in our
// image being flipped.
matrix.m[0][0] *= -1;
matrix.m[1][1] *= -1;
// Let's also shear it. While mirroring/flipping could easily be done with the DrawImageTransform methods,
// doing more complex matrix manipulation (like shearing) can only be done with the DrawImageMatrix function.
matrix.m[0][1] = 2;
// And then we just make a call to DrawImageMatrix and give it our specified XY coordinates as well,
// and that's it! This works in both 2D and 3D modes.
g->DrawImageMatrix(IMAGE_HUNGARR_LOGO, matrix, 300, 400);
// IMPORTANT COMPARISON NOTE:
// DrawImageTransform/F will try to use the faster drawing methods if it recognizes certain
// common transforms, like rotating and scaling. This only works though if you are using
// either one operation, or multiple operations of the same type (i.e. you only used scale
// or rotate with the Transform object, or used the same one multiple times). If you mix
// operations, like we do above, the DrawImageTransform method will actually use DrawImageMatrix.
// With DrawImageTransform, you can't directly modify the underlying matrix, so if that's something
// you need to do, then DrawImageMatrix is a better option.
}
void Board::ButtonDepress(int id)
{
if (id == mDemoButton->mId)
{
delete mDemoWidget;
mDemoWidget = new DemoWidget();
mApp->mWidgetManager->AddWidget(mDemoWidget);
// What, more flags? Yup. Since our little DemoWidget isn't a dialog, when we add it,
// it won't change anything about the widgets drawn below it. Which means, unmodified,
// mouse clicks could still be passed down to the board (if the click wasn't in the DemoWidget),
// the board still updates, still draws, etc. Let's turn off mouse clicks for all widgets below the
// DemoWidget. But, let's still allow all widgets below it to update. Note that if we used the form
// of the method that only takes one parameter, then it would use mDefaultBelowModalFlagsMod
// which we modified in our app. By passing in our own flags though, they're used instead.
// Which means the only flag we need to remove from the widgets below it is the allow mouse flag.
// We do that by making a temp FlagsMod object, and setting
// its mRemoveFlags variable to be ORed with WIDGETFLAGS_ALLOW_MOUSE. Upon calling
// the WidgetManager's AddBaseModal method, we then pass in the DemoWidget, and the above flags.
// AddBaseModal will then treat this new widget as a modal object, applying any flags we passed in.
FlagsMod flags;
flags.mRemoveFlags |= WIDGETFLAGS_ALLOW_MOUSE;
mApp->mWidgetManager->AddBaseModal(mDemoWidget, flags);
}
else if (id == mDialogButton->mId)
{
// 1.2版本增加了创建对话框的更简单的方法.
// 以前在第5个例子中. 我们创建对话框前先要重写 SexyAppBase::NewDialog() 函数. 在其中指定缺省时对话框的皮肤,对话框按钮皮肤等...
// 现在可以不必这样了. 我们可以创建没有皮肤的对话框. 这在快速原型开发或者测试时是很方便的.
Dialog* d = mApp->DoDialog(100, true, _S("Fun Dialog"), _S("Line 1\nLine 2\nLine 3"), _S("Close!"), Dialog::BUTTONS_FOOTER);
// 可以不指定其字体. 如果没有指定一个字体. 则对话框使用系统默认字体.
// d->SetButtonFont(FONT_DEFAULT);
}
else if (id == mCurtainButton->mId)
{
mCurtainMode = CURTAIN_CLOSING;
mCurtainWidth = 0;
while ((mCurtainMode != CURTAIN_INACTIVE) && mApp->UpdateApp())
{
if (mCurtainMode == CURTAIN_CLOSING)
{
mCurtainWidth += 4;
if (mCurtainWidth >= mWidth / 2)
{
mCurtainWidth = mWidth / 2;
mCurtainMode = CURTAIN_OPENING;
}
}
else
{
mCurtainWidth -= 4;
if (mCurtainWidth <= 0)
{
mCurtainWidth = 0;
mCurtainMode = CURTAIN_INACTIVE;
}
}
}
}
}
//DemoWidget.cpp
#include "DemoWidget.h"
#include "Res.h"
#include "SexyAppFramework/WidgetManager.h"
#include "SexyAppFramework/ButtonWidget.h"
#include "V12DemoApp.h"
using namespace Sexy;
//
//
DemoWidget::DemoWidget()
{
// 调整大小
int w = 200, h = 200;
Resize(gSexyAppBase->mWidth / 2 - w / 2, gSexyAppBase->mHeight / 2 - h / 2, w, h);
// 以前, 要把一个 widget 做为子窗口插入另一个 widget 是很烦人的.
// 所以以前的例子中你必须重写 AddedToManager/RemovedFromManager 函数....等等...
// 现在可以直接在父部件的构造函数中创建子部件. 可以用成员函数 AddWidget() 将子部件插入.
// 而且. 在父部件的析够函数中. 也只要在 delete 子部件前加上一句 RemoveAllWidgets() 就可以方便的从部件管理器中移除所有子部件了.
mMoveButton = new ButtonWidget(0, this);
mMoveButton->mLabel = _S("MOVE");
mMoveButton->SetFont(FONT_DEFAULT);
mCloseButton = new ButtonWidget(1, this);
mCloseButton->mLabel = _S("CLOSE");
mCloseButton->SetFont(FONT_DEFAULT);
// 方便的将 mMoveButton 做为该类对象的子部件.
AddWidget(mMoveButton);
AddWidget(mCloseButton);
mMoveButton->Resize(10, 150, 75, 50);
mCloseButton->Resize(115, 150, 75, 50);
// 部件的优先级(也就是 Z顺序). 缺省为0. 它越大越绘制在顶层.
mPriority = 1;
}
//
//
DemoWidget::~DemoWidget()
{
// 在delete 子部件们之前. 需要用 RemoveAllWidgets() 将所有子部件从部件管理器中 remove.
// 这个函数也可以带参数:
// RemoveAllWidgets(bool doDelete = false, bool recursive = false);
// 其中第一个参数为在移除子部件时. 是否顺便将其 delete... 这个也很有用..
// 第二个参数为是否也递归的调用子部件的 RemoveAllWidgets() .
RemoveAllWidgets();
delete mMoveButton;
delete mCloseButton;
}
//
//
void DemoWidget::ButtonDepress(int id)
{
if (id == mMoveButton->mId)
{
// 现在. 要移动一个部件只要调用其 Move() 函数即可.
// 它在移动的时候也同时会自动的移动其内部的子部件.
// 但是在以前的版本中. 则只能手动的一个一个移动这些子部件.
Move(Rand() % (gSexyAppBase->mWidth - mWidth), Rand() % (gSexyAppBase->mHeight - mHeight));
}
else if (id == mCloseButton->mId)
{
// 从部件管理器中移除 "当前部件"自己.
gSexyAppBase->mWidgetManager->RemoveWidget(this);
}
}
//
//
void DemoWidget::Draw(Graphics* g)
{
g->SetColor(Color(0, 255, 0, 200));
g->FillRect(0, 0, mWidth, mHeight);
}
// v12DemoApp.cpp
#include "V12DemoApp.h"
#include "SexyAppFramework/WidgetManager.h"
#include "SexyAppFramework/DDImage.h"
#include "SexyAppFramework/ResourceManager.h"
#include "SexyAppFramework/Dialog.h"
#include "SexyAppFramework/SWTri.h"
#include "Board.h"
#include "Res.h"
using namespace Sexy;
V12DemoApp::V12DemoApp()
{
mProdName = "V12Demo";
mProductVersion = "1.0";
mTitle = StringToSexyStringFast("SexyAppFramework: " + mProdName + " - " + mProductVersion);
mRegKey = "PopCap\SexyAppFramework\V12Demo";
mNoSoundNeeded = true;
mBoard = NULL;
// 必须调用下面的函数. 它告诉程序可以使用 DrawImageTransform 和 DrawImageMatrix 函数.
// 为什么要手动调用? 因为如果不使用它们可以使exe文件减少 400K(压缩后150K). 所以提供了一个选择的机会.
SWTri_AddAllDrawTriFuncs();
}
V12DemoApp::~V12DemoApp()
{
delete mBoard;
}
void V12DemoApp::ShutdownHook()
{
if (mBoard != NULL)
mWidgetManager->RemoveWidget(mBoard);
}
void V12DemoApp::InitHook()
{
LoadResourceManifest();
if (!mResourceManager->LoadResources("Init"))
{
mLoadingFailed = true;
ShowResourceError(true);
return;
}
if (!ExtractInitResources(mResourceManager))
{
mLoadingFailed = true;
ShowResourceError(true);
return;
}
// This is new. Widgets now contain flags that alter the behavior of them.
// Please read the document included with the 1.2 release for a full description,
// but here's the general rundown:
// The WidgetManager's mDefaultBelowModalFlagsMod contains flags that are applied
// anytime a dialog box pops up on screen. If we modify these, then we modify the
// default behavior for ALL dialog boxes, and don't have to mess around with other
// function calls and setting of misc. variables. All flags variables contain 2
// sub-variables: mAddFlags and mRemoveFlags. By ORing stuff with mAddFlags, when
// a dialog box pops up, the flags in mAddFlags are applied in addition to any
// other flags that exist. Similarly, mRemoveFlags contains flags that are removed
// from a widget when the dialog pops up. Below, what we're saying is that when
// a dialog box pops up, we DO NOT want any widgets beneath it to be able to update.
// What'll happen is that any widget below the dialog gets the WIDGETFLAGS_UPDATE
// flag removed. This will of course be restored when the dialog box closes.
// Again, please see the 1.2 doc for a list of all the flags and a much more
// thorough explanation.
mWidgetManager->mDefaultBelowModalFlagsMod.mRemoveFlags |= WIDGETFLAGS_UPDATE;
mBoard = new Board(this);
mBoard->Resize(0, 0, mWidth, mHeight);
mWidgetManager->AddWidget(mBoard);
}
void V12DemoApp::LostFocus()
{
if (mBoard)
mBoard->SetFocusLost(true);
}
void V12DemoApp::GotFocus()
{
if (mBoard)
mBoard->SetFocusLost(false);
}
// 新的对话框按钮事件处理方法:
// 只需在 app 类的DialogButtonDepress() 函数中检查 指定对话框的指定按钮. 就可以指定执行它的响应操作.
void V12DemoApp::DialogButtonDepress(int dialog_id, int button_id)
{
if ((dialog_id == 100) && (button_id == Dialog::ID_OK))
KillDialog(100);
}
//main.cpp
//
// main.cpp
//
// ***********************************************************************
// 这个例子介绍1.2版的新特性.
// 当然. 你需要先看 例子1 到 例子5 学习一些基础的知识.
// ***********************************************************************
//
// * 用新的 InitHook()/ShutdownHook() 来做初始化和退出时的工作. 而不再需要重写基类的 Init().
//
// * 在App类的 DialogButtonDepress() 中处理特定对话框的特定按钮事件.
//
// * 可以在不指定皮肤的情况下创建对话框. 这在快速开发或调试的时候很有用.
//
// * 用 flags 修改 widget 的行为. 例如"总是marking dirty", "不允许鼠标事件" 等.
//
// * 更简便的 将一个 widget 做为子窗口插入另一个 widget.
//
// * 怎么在顶层绘制. 怎么绘制在所有部件之上. 怎么根据"优先级"确定它们的 Z 顺序.
//
// * push/pop graphics对象的状态.
//
// * 用新的 Graphics::DrawImageTransform/F 来更好的 旋转/缩放/转换图像.
//
// * 用新的 Graphics::DrawImageMatrix 绘制 2D/3D with a matrix.
//
// * How to use UpdateApp to help with transitions
//
#include "V12DemoApp.h"
using namespace Sexy;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
gHInstance = hInstance;
V12DemoApp* anApp = new V12DemoApp();
anApp->Init();
anApp->Start();
delete anApp;
return 0;
}
popcap sexyframework - 该库在1.2版的变化 详见main.cpp
最新推荐文章于 2019-09-12 18:44:56 发布