Simple Win32 Program

Rational: I wanted to create an archetype program that would be able to handle multiple key combinations. Say, the right shift key and the the key character 'X'. My options available OIS, MFC, or WxWindows. MFC and WxWindows would be a lot overhead and dll version management for what is a simple program. After unsuccseful attempts at making OIS work I decided that the [Petzold:http://en.wikipedia.org/wiki/Charles_Petzold] style of program would minimize the windows "portion" and show how ogre would need to interact. When finished this program would show the classic orgehead mesh, respond to a few key inputs and adjust to camera position in response to the mouse or the keyboard.

First this program was created with Microsoft Visual Studio 2003 and links to the einhort version 1.3.0 of ogre library. The easiest way to start off is to use the wizard to create a simple windows application ogre32,which should give you the following files: 

ogre32.cpp
ogre32.h
ogre32.ico
ogre32.ncb
ogre32.rc
ogre32.sln
ogre32.vcproj
ReadMe.txt
Resource.h
small.ico
stdafx.cpp
stdafx.h

Before modifying the code that the wizard created you will need to get the media files and scripts necessary to display the ogrehead.mesh file. To do this you will need to create the directory 'media' under your main project and copy the following files into this directory. The png and jpg files can be found in the one of textures directory. The Ogre.material file is modified version of the Ogre.material file that comes with ogre source code. The origininal can be found at .\ogrenew\Samples\Media\materials\scripts. 

cursor.png
dirt01.jpg
GreenSkin.jpg
Ogre.material
ogreborder.png
ogreborderUp.png
ogrehead.mesh
spheremap.png
WeirdEye.png

You will need to create three configuration files: 

ogre.cfg
Plugins.cfg
resources.cfg

ogre.cfg


Render System=Direct3D9 Rendering Subsystem

[Direct3D9 Rendering Subsystem]
Allow NVPerfHUD=No
Anti aliasing=None
Floating-point mode=Fastest
Full Screen=No
Rendering Device=NVIDIA GeForce FX 5200
VSync=No
Video Mode=800 x 600 @ 32-bit colour

[OpenGL Rendering Subsystem]
Colour Depth=32
Display Frequency=60
FSAA=0
Full Screen=Yes
RTT Preferred Mode=FBO
VSync=No
Video Mode=1024 x 768

Plugins.cfg


# Defines plugins to load

# Define plugin folder
PluginFolder=.

# Define plugins
Plugin=RenderSystem_Direct3D9

resources.cfg

# Resource locations to be added to the default path
[General]
FileSystem=./media


You will need to edit the follow files: 

stdafx.h
ogre32.cpp

stdafx.h

#pragma once


#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <Ogre.h>    //brings in most everything

 

ogre32.cpp

The following is the original ogre32.cpp file This will create a simple project that displays the ogrehead mesh file.

// ogre32.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "ogre32.h"
#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;            // current instance
TCHAR szTitle[MAX_LOADSTRING];        // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];    // the main window class name

using namespace Ogre; // <-- ultimate in lazy

 

The most important of the following variables is mRoot. As the "Root class represents a starting point for the client application. From here, the application can gain access to the fundamentals of the system ... and Root must be created before any other Ogre operations are called. Once an instance has been created, the same instance is accessible throughout the life of that object by using Root::getSingleton (as a reference) or Root::getSingletonPtr (as a pointer). " See http://www.ogre3d.org/docs/api/html/classOgre_1_1Root.html#_details for more details.

Please consult the wiki for more detailed reasons on why we added each of these variables.

Root *mRoot             = 0;  // 
SceneManager *mSceneMgr = 0;  // 
Camera *mCamera         = 0;  // 
Viewport* mViewPort     = 0; 
RenderWindow* mRenderWindow=0; 

// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
     // TODO: Place code here.
    MSG msg;
    HACCEL hAccelTable;
    HWND hWnd;
    // Initialize global strings
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_OGRE32, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    
    hInst = hInstance; // Store instance handle in our global variable

    hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

    if (!hWnd)
    {
        return FALSE;
    }

create the root ogre system

mRoot = new Root();

 load the configuration file why?

    ConfigFile cf;
    cf.load("resources.cfg");

    ConfigFile::SectionIterator seci = cf.getSectionIterator();

    String secName, typeName, archName;
    while (seci.hasMoreElements())
    {
        secName = seci.peekNextKey();
        ConfigFile::SettingsMultiMap *settings = seci.getNext();
        ConfigFile::SettingsMultiMap::iterator i;
        for (i = settings->begin(); i != settings->end(); ++i)
        {
            typeName = i->first;
            archName = i->second;
            ResourceGroupManager::getSingleton().addResourceLocation(
                archName, typeName, secName);
        }
    }

 Load the directx rendering system we dont have to Display the configuration dialog.

RenderSystemList *rsList = mRoot->getAvailableRenderers();
    int c=0;
    bool foundit = false;
    RenderSystem *selectedRenderSystem=0;
    while(c < (int) rsList->size())
    {
        selectedRenderSystem = rsList->at(c);
        String rname = selectedRenderSystem->getName();
        if(rname.compare("Direct3D9 Rendering Subsystem")==0)
        {
            foundit=true;
            break;
        }
        c++; // <-- oh how clever
    }
    if(!foundit) 
        return FALSE; //we didn't find it

    //we found it, we might as well use it!
    mRoot->setRenderSystem(selectedRenderSystem);

    selectedRenderSystem->setConfigOption("Full Screen","No");  
    selectedRenderSystem->setConfigOption("Video Mode","800 x 600 @ 16-bit colour");

    //retrieve the config option map
    ConfigOptionMap comap = selectedRenderSystem->getConfigOptions();

    //and now we need to run through all of it
    ConfigOptionMap::const_iterator start = comap.begin();
    ConfigOptionMap::const_iterator end = comap.end();
    while(start != end)
    {
        String OptionName = start->first;
        String CurrentValue = start->second.currentValue;
        StringVector PossibleValues = start->second.possibleValues;
        int c=0;
        while (c < (int) PossibleValues.size())
        {
            String OneValue = PossibleValues.at(c);
            c++;
        }
    start++;
    }    
    //end boilerplate

 this is the magic! here is where we take the window that has been previously been created and attach ogre to it.

mRoot->initialise(false,"Some Window Title");
    NameValuePairList misc;
    misc["externalWindowHandle"] = StringConverter::toString( (size_t)hWnd);
    mRenderWindow = mRoot->createRenderWindow( "My sub render window", 800, 600, false, &misc );

 create a scene manager

// choose sm
    mSceneMgr = mRoot->createSceneManager(ST_GENERIC, "mSceneMgr");
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));

This is so we can have scripts work and the mesh is properly rendered.

ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

 Load a mesh that is located in the ./media directory.

Entity *ent1 = mSceneMgr->createEntity( "ogre", "ogrehead.mesh" );
        SceneNode *node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode( "RobotNode" );
        node1->attachObject( ent1 );

 Create a camera so we can look at his lovely mug.

// --------------------
    // Create the camera
    mCamera = mSceneMgr->createCamera("PlayerCam");
    // Position it at 500 in Z direction
    mCamera->setPosition(Ogre::Vector3(0,0,500));
    // Look back along -Z
    mCamera->lookAt(Ogre::Vector3(0,0,-300));
    mCamera->setNearClipDistance(5);
    // Set the viewport
    mViewPort = mRenderWindow->addViewport(mCamera);
    mViewPort->setBackgroundColour(Ogre::ColourValue(0.0f, 0.0f, 0.0f, 1.0f)); 

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    
    hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_OGRE32);

    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0)) 
    {       
                //placing renderOneFrame seems to allow for a clean shutdown.
                //thanks to user lakin for that hint.
        if (mRoot->renderOneFrame()) 
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}


ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX); 

    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = (WNDPROC)WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = LoadIcon(hInstance, (LPCTSTR)IDI_OGRE32);
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = NULL;
    wcex.lpszClassName    = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

    return RegisterClassEx(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message) 
    {
    case WM_COMMAND:
        wmId    = LOWORD(wParam); 
        wmEvent = HIWORD(wParam); 
        // Parse the menu selections:
        switch (wmId)
        {
        case IDM_EXIT:

 I was told to do this. This may or may not be necessary.

        mRoot->detachRenderTarget(mRenderWindow);
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        // TODO: Add any drawing code here

        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
 
        PostQuitMessage(0);
        break;

 Returning 1 will cause the screen not flicker when the window is being resized.

case WM_ERASEBKGND:
      return 1;

 Handle resizing the window. one of the things this program does not do is display full screen. This should be relatively simple to implement. Also the section is direct translation of the WxWindows code that was posted to forum.

case WM_SIZE:
        if (mCamera) 
        { 
            RECT rect; 
            GetClientRect(hWnd,&rect); 

            // notify "render window" instance 
            mRenderWindow->windowMovedOrResized(); 

            // Adjust camera's aspect ratio, too 
            if ((rect.bottom - rect.top) != 0 && mCamera != 0) 
                mCamera->setAspectRatio((Ogre::Real)mRenderWindow->getWidth() / (Ogre::Real)mRenderWindow->getHeight()); 
            mCamera->yaw(Radian(0));
            Root::getSingletonPtr()->renderOneFrame(); 
        }

        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

#endif

时间: 2024-09-15 13:41:15

Simple Win32 Program的相关文章

VC++ WIN32 sdk实现按钮自绘详解 之二.

网上找了很多,可只是给出代码,没有详细解释,不便初学者理解.我就抄回冷饭.把这个再拿出来说说. 实例图片:    首先建立一个标准的Win32 Application 工程.选择a simple Win32 Application. 然后建立我们的资源文件首先新建一个对话框资源,资源ID改为IDD_MAIN_DLG 然后在其上新建一个按钮控件资源ID改为IDC_ODBUTTON,此按钮的styles中必须选中owenerdraw属性. 然后将其保存为.rc的资源文件.并将其导入我们的工程.同理新

深入详解C编写Windows服务程序的五个步骤_C 语言

Windows 服务被设计用于需要在后台运行的应用程序以及实现没有用户交互的任务.为了学习这种控制台应用程序的基础知识,C(不是C++)是最佳选择.本文将建立并实现一个简单的服务程序,其功能是查询系统中可用物理内存数量,然后将结果写入一个文本文件.最后,你可以用所学知识编写自己的 Windows 服务. 当初我写第一个NT 服务时,我到 MSDN 上找例子.在那里我找到了一篇 Nigel Thompson 写的文章:"Creating a Simple Win32 Service in C++&

关于“C# Applet”

下面一段文字来自C# Expert, I am wondering how to build a C# applet. I built a class library with a custom control. But the browser (IE6) fails to render it as an object. Do you have some examples to show how to achieve this? By the way, can a C# applet be ru

Linux下用C语言API连接MySQL数据库

像PHP和perl一样,MySQL也提供的C语言使用的API. C代码的API是随MySQL一起发布的. 它包含在mysqlclient库中, 可以使C程序来访问数据库. MySQL源码包中的许多客户端都是用C写的. 如果你正在找使用这些C API的例子, 可以看看客户端的写法.你可以在MySQL源码包的clients目录找到这些例子. 软件包 请确保你已经安装了必要的开发环境,比如gcc, mysql等等. 下面是编译一个程序所需要安装的软件包的列表 (Ubuntu为例): mysql-cli

用C编写Windows服务程序的五个步骤

Windows 服务被设计用于需要在后台运行的应用程序以及实现没有用户交互的任务.为了学习这种控制台应用程序的基础知识,C(不是C++)是最佳选择.本文将建立并实现一个简单的服务程序,其功能是查询系统中可用物理内存数量,然后将结果写入一个文本文件.最后,你可以用所学知识编写自己的 Windows 服务. 当初我写第一个NT 服务时,我到 MSDN 上找例子.在那里我找到了一篇 Nigel Thompson 写的文章:"Creating a Simple Win32 Service in C++&

在 Mac OS X 装不上 TensorFlow?看了这篇就会装

这个文档说明了如何在 Mac OS X 上安装 TensorFlow. 注意:从 1.2 版本开始,在 Mac OS X 上 TensorFlow 不再支持 GPU. 确定如何安装 TensorFlow 你可以选择一种方式安装 TensorFlow,支持下面的几种选择: virtualenv "本地" pip Docker 从源代码安装,更专业有单独的文档记录 我们建议使用 virtualenv 安装.virtualenv 是一个和其它 Python 项目开发隔离的虚拟 Python

[python] 安装numpy+scipy+matlotlib+scikit-learn及问题解决

这篇文章主要讲述Python如何安装Numpy.Scipy.Matlotlib.Scikit-learn等库的过程及遇到的问题解决方法.最近安装这个真是一把泪啊,各种不兼容问题和报错,希望文章对你有所帮助吧!你可能遇到的问题包括:         ImportError: No module named sklearn 未安装sklearn包         ImportError: DLL load failed: 找不到指定的模块         ImportError: DLL load

HMM的介绍及实现

HMM基本原理 Markov链:如果一个过程的"将来"仅依赖"现在"而不依赖"过去",则此过程具有马尔可夫性,或称此过程为马尔可夫过程.马尔可夫链是时间和状态参数都离散的马尔可夫过程.HMM是在Markov链的基础上发展起来的,由于实际问题比Markov链模型所描述的更为复杂,观察到的时间并不是与状态一一对应的,而是通过一组概率分布相联系,这样的模型称为HMM.HMM是双重随机过程:其中之一是Markov链,这是基本随机过程,它描述状态的转移,是

工作流引擎Activiti 专题

https://github.com/Activiti/Activiti Quick Start Guide This quick start assumes: Familiarity with Maven and Java A development environment with Java The following variables will be referenced in this tutorial Variable Description $mvnProject The root