在Symbian exe 程序中显示图形

在Symbian exe 程序中显示图形

Displaying graphics in Symbian exe programs.
在 Symbian exe 程序中显示图形
 
Generally, exe programs are used to implement servers (exedll, epocexe target type) or

simple console programs. This may lead to believe that graphical features are not available

for exe programs. This is not the case, and even though it might take some extra work to

set up an appropriate environment, this is quite straight forward to achieve, as the

following snippet will illustrate. This way, we can make use of graphics without having to

resort on a full blown application.
    通常,通常EXE程序(exedll, epocexe 类型)被用来实现服务器端或者是简单的控制台程序。所以使大家认为图形化的特性对于exe程序是不必要的。事实上并非如此,甚至它需要做一些额外的工作来设置一个适当的环境,就像下面将举例提到的,是十分方便的。

Our aim is to simply emulate the minimum set up provided by the framework when an

application (.app) is loaded. Being a dll, an application needs a process to attach to.

This is provided by AppRun.exe, which besides catering its own process and thread, calls

EikDll::RunAppInsideThread(), which -among other things- creates a CONE environment

(CCoeEnv)

    我们的目标很简单,就是模拟当应用程序(.app)被加载时框架所提供的最小配置。作为一个DLL,应用程序是需要一个进程去加载它的,AppRun.exe就是用来做这个的。AppRun.exe不仅为自己的进程和线程提高资源,它还调用EikDll::RunAppInsideThread() ,建立一个CONE环境(CCoeEnv) 。

When a CONE Environment is created, it sets up a cleanup stack, active scheduler

(CCoeScheduler), and sessions to the file and window server (which can be later retrived by

calling CCoeEnv::FsSession() and CCoeEnv::WsSession()). Then it creates a screen, a window

group and a graphic context, among other things. Later, after the NewApplication() factory

function is called by the framework, the CCoeAppUi (from where the application's AppUi

derives) creates the control stack, view manager, etc. and the CCoeControl derived class

will create a window (RWindow) to provide a basic view. As you can see, this snippet

provides all this basic functionality at once, without extra bloat such as a control stack,

etc. which aren't needed in this simple case. I haven't included comments, as most of the

code speaks by itself.

    当CONE环境建立后设置清理栈活动对象规划器(CCoeScheduler),建立和文件,窗口服务器的会话(以后会在调用CCoeEnv::FsSession() 和 CCoeEnv::WsSession()时用到)。接着创建屏幕,窗口组和图形上下文。再下来,在工厂函数NewApplication()被框架调用后,CCoeAppUi (来自应用程序的AppUi驱动)建立控件栈,视图管理器等等。CCoeControl的继承类将建立窗口(RWindow)来提供基本的视图。就像你所看到的,这个程序片断只提供了所以基本的功能,并没有像控件栈等这些多余的东西,它们是这个简单例子程序中所不需要的。我们并没有注释,因为代码本身已经说明问题了。

LOCAL_C void ExeMainL()
{
    RWsSession ws;
    User::LeaveIfError(ws.Connect());
    CleanupClosePushL(ws);

    CWsScreenDevice* screen = new(ELeave) CWsScreenDevice(ws);
    CleanupStack::PushL(screen);
    screen->Construct();

    RWindowGroup wg(ws);
    User::LeaveIfError(wg.Construct(reinterpret_cast<TUint32>(&wg), EFalse));
    CleanupClosePushL(wg);

    wg.SetOrdinalPosition(10, ECoeWinPriorityAlwaysAtFront);

    CWindowGc* gc;
    User::LeaveIfError(screen->CreateContext(gc));
    CleanupStack::PushL(gc);

    RWindow window(ws);
    User::LeaveIfError(window.Construct(wg, reinterpret_cast<TUint32>(&wg) + 1));
    CleanupClosePushL(window);
    window.SetBackgroundColor(TRgb(0x90, 0x90, 0x90));
    window.Activate();
    window.SetExtent(TPoint(0, 0), TSize(screenWidth, screenHeight));
    window.SetVisible(ETrue);

    gc->Activate(window);
    TRect rect = TRect(window.Size());
    window.Invalidate(rect);
    window.BeginRedraw(rect);

    gc->SetBrushStyle(CGraphicsContext::ESolidBrush);
    gc->Clear();

    TInt64 seed = User::TickCount();
    TRgb color[] = { KRgbRed, KRgbGreen, KRgbBlue, KRgbYellow, KRgbCyan };

    for (TUint i = 0; i < 10000; ++i)
    {
        TInt x = Math::Rand(seed) % screenWidth;
        TInt y = Math::Rand(seed) % screenHeight;
        TInt w = Math::Rand(seed) % 50;
        TInt h = Math::Rand(seed) % 25;

        TRect rect(TPoint(x, y), TSize(w, h));
        gc->SetBrushColor(color[i % sizeof color]);
        gc->DrawRect(rect);
    }

    window.EndRedraw();
    gc->Deactivate();

    ws.Flush();

    CleanupStack::PopAndDestroy(5, &ws);    // window, gc, wg, screen, ws
}
Let's see now the entry point of the program. If we tried something like this
现在我们来看入口程序。如果我们这样做:

GLDEF_C TInt E32Main()
{
    __UHEAP_MARK;
    CTrapCleanup* cleanup = CTrapCleanup::New();

    TRAPD(error, ExeMainL());
    __ASSERT_ALWAYS(!error, User::Panic(_L("EXEUI"), error));

    delete cleanup;
    __UHEAP_MARKEND;

    return 0;
}
it would work on the device only. On the emulator, you'd get a panic, as

RWsSession::Connect() would fail. The reason for this is that when an exe is executed, the

emulator doesn't launch the window server as part of its initialization, whereas on the

device the server is already loaded.
    它只能在真机(手机)上运行。在模拟器上你会得到一个严重错误,因为RWsSession::Connect() 会失败。原因是当一个exe程序在模拟器上运行的时候,它(模拟器)是不会启动窗口服务器作为其初始化的一部分的。但是在手机上窗口服务器总是运行着的。

There're a couple of ways to solve this. On Series 60 SDK v1.2, there's an undocumented

function which does exactly this for us. RegisterWsExe() is provided by wserv.lib. So now

our entry point function is:
有许多方法解决这个问题。在Series 60 SDK v1.2,有一个未公开的函数为我们解决了这个问题。

wserv.lib提供了RegisterWsExe()这个函数。现在我们的入口函数:

void RegisterWsExe(const TDesC&);

GLDEF_C TInt E32Main()
{
    __UHEAP_MARK;
    CTrapCleanup* cleanup = CTrapCleanup::New();

#if defined(__WINS__)
    RegisterWsExe(_L("ExeUI.exe"));
#endif

    TRAPD(error, ExeMainL());
    __ASSERT_ALWAYS(!error, User::Panic(_L("EXEUI"), error));

    delete cleanup;
    __UHEAP_MARKEND;

    return 0;
}
The problem with this solution is that it's not as generic as we might want. There's

another way, which requires some more bit of work, that consists of changing the target

type to exedll or epocexe. This means that on WINS (emulator) we get a .dll, and on MARM

(target) we get the .exe as usual. Note that all changes will be made to the startup code,

that is, no changes are made to ExeMainL() code.
    这个解决方案并不是我们所通常所希望的。有另外一种方式,只需要多做一点儿工作,包括把目标类型,改为exedll 或 epocexe。这意味着在模拟器上我们得到的是 .dll,在ARM(手机)上是通常的.exe。要注意所需要修改的仅仅是启动代码上,ExeMainL()使没有变化的。

This is how our new startup code looks, with the two functions required by the exedll type

(epocexe is analogous, except the exported function InitEmulator() is replaced by WinsMain

()):
我们的启动代码看起来是这样的,下面是exedll所必须的两个函数(epocexe是类似的,除非导出函数

InitEmulator()被WinsMain()所取代):

GLDEF_C TInt E32Main()
{
    __UHEAP_MARK;
    CTrapCleanup* cleanup = CTrapCleanup::New();

    TRAPD(error, ExeMainL());
    __ASSERT_ALWAYS(!error, User::Panic(_L("EXEUI"), error));

    delete cleanup;
    __UHEAP_MARKEND;

    return 0;
}

// If using exedll target type
#if defined(__WINS__)
EXPORT_C TInt InitEmulator()
{
    E32Main();
    User::Exit(0);
    return KErrNone;
}

TInt E32Dll(TDllReason)
{
    return KErrNone;
}
#endif
Now the idea is renaming ExeUI.dll to ExeUI.app, and copying it to an application directory

on the emulator tree to make it look like an ordinary application. So we create the ExeUI

directory in Epoc32/Wins/c/system/Apps (or Epoc32/Release/wins/udeb/z/system/apps if you

wish). As we're creating an application, we also need to provide it of a proper UID, so

don't forget to add the corresponding line in the .mmp
Now you may launch the emulator, that will show the ExeUI program's default icon.

     现在所要做的工作就是把把ExeUI.dll改名为ExeUI.app,并拷贝到模拟器的一个应用程序目录下。我们建立ExeUI目录Epoc32/Wins/c/system/Apps (或 Epoc3/Release/wins/udeb/z/system/apps只要你愿意)我们这不是建立了一个应用程序吗,所以我们还要提供一个合适的UID,别忘了在.mmp文件相应的地方添加它。好了,你启动模拟器,它会显示ExeUI程序的默认图标了。
(转自:开发视界)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值