在VC6中基于dll开发插件用于各种图片显示,写一个小程序来检测10bet手机官网
分类:面向对象

#include "hge.h"
#include "hgesprite.h"

一、图片显示

三维图形的这是opengl的强项,大型3D游戏都会把它作为首选。
图像处理,是opencv的锁定的目标,大多都是C的api,也有少部分是C++的,工业图像表现,图像识别,都会考虑opencv的。
webgl,这是3维向web延伸的方案,它可以直接调用支持opengl的接口,硬件加速或者软件模拟,很强大,结和html5....
blender,可以完成三维模型制作,3D动画制作了。

如何使用VC来检测系统上的.NetFrameWork版本呢,原理见我前面刚刚写过,不懂的可以去看一下,下面直接贴代码了,百度呀,为什么没有贴代码的功能呢,哎直接贴真恶心呀,那就恶心一下吧。

const int screen_width = 535;
const int screen_height = 656;

图片显示的方法:

#include “stdio.h”
#include “windows.h”
#include “tchar.h”
#include “strsafe.h”
#include “stdafx.h”

HGE *hge = NULL;

1.  直接写程序

 

 

hgeSprite *spr;//声明一个精灵类指针;

2.  第3方库

 PC 游戏还是 DirectX 开发?
事实上在早年OpenGL即使在游戏领域也是对DirectX压倒性的优势。John Carmack曾嘲讽DirectX是“horribly broken” 的API。
直到DirectX6时代OpenGL都被认为是比DirectX更加优秀的API,即使那个时候DirectX已经有《CS》《极品飞车5》等大作的支持,却依然不受当时FPS游戏霸主id Software的待见。作为那个时代的显卡杀手,《Quake III》都仅仅只支持OpenGL。

DirectX7发布之后DirectX和OpenGL开始逐渐平起平坐。直到2000年DirectX8的发布才使DirectX在游戏领域完全确立了自己的优势 —— 支持革命性的programmable GPU rendering pipeline来代替原有的fixed function pipeline,引入了Vertex Shader和Pixel Shader。而OpenGL的核心正式支持programmable rendering pipeline已经是四年之后OpenGL 2.0发布的时候了。想想这中间会有多少游戏公司/游戏引擎公司会倒向DirectX吧。
说到OpenGL衰落的原因,不得不提到OpenGL开发的机制。OpenGL早期一直是由ARB (
OpenGL Architecture Review Board,成员包括Nvidia, ATI, Intel, Apple, IBM, SGI等等)成员共同维护。每个成员可以为了支持自己硬件新的feature来开发OpenGL enxtension, 所有成员一致通过的extension才能加入到下个版本OpenGL核心中。这就造成了不同成员为了各自利益互相斗争,拖慢了开发进度。微软曾经也是ARB的成员之一,后来因为受不了这种机制退出专心搞自己的DirectX去了。
如果一个API越流行,那么去学习这个API的人就会越多,游戏公司会越容易招到掌握这个API的图形程序员,也就会更多的基于这个API开发游戏。用这个API的游戏越来越多,就会更多的得到
硬件厂商的支持,为面向这个API的驱动做更多的优化,然后这个API就会更加流行。如此进入一个良性循环,这就造成了DirectX现在称霸游戏领域,OpenGL几乎绝迹的局面。
在06年从ARB交由Khronos Group掌管之后, OpenGL最近几年也迎头赶上,从性能,易用性来说其实和DirectX已经相差不大。但是在相比DirectX没有突出优点的情况下(除了跨平台),已经习惯使用DirectX的游戏厂商也不可能重新投出OpenGL的怀抱。

最后一点,OpenGL只是一个单纯的图形库,而DirectX是包含图形(Direct3D), 声音(DirectSound), 输入(DirectInput), 网络(DirectPlay)的一整套游戏开发解决方案。对开发者来说使用DirectX显然要方便的多。
/*******************************************************************************************************/
下面是我之前一个同事看完我的回答的评论,也贴上来吧。
“还有很重要的一点, GL从不淘汰任何老的API. DX10相对于DX9,是个全新的API,革命性的更新,彻底推倒重来. 但GL为了向后兼容,保留了很多对硬件和驱动都不友好的API.除了跨平台和早期对精度的要求比DX高,其他简直是一无是处”


于是Game开发者就都去用DX了。如果Linux上有类似于DX的接口,只要它真正被广泛支持了,包括但不限于OpenGL DSA 扩展,相信我,没有哪个开发者会脑袋抽风继续跟随坑爹的状态机的。

OpenGL的硬件兼容性不如DirectX。用OpenGL写一个程序,在nVidia上跑起来了,百分之八十是没法在intel上跑,百分之九十九没法在AMD上跑。OpenGL直到目前为止如果不用DSA的话,设置一个对象的属性还得先绑定,这样一来就使得code变得高度依赖于一个时刻在变的状态,而且很多驱动的实现某些特定的状态下有各种bug,极难调试。例如我之前在intel上跑一个程序,如果不每帧都重新设置一个framebuffer object的render target, 那个framebuffer到了下一帧就莫名其妙的失效了,而在NV和AMD上都没有此问题,但是AMD又出了另外一个问题。

DirectX的好处有微软帮你测试兼容性。一个驱动想拿到WDDM认证,先得跑通积累了十几年的test set,这样一来在实际中遇到问题的可能性就大为减少了。另外DX有开发调试环境的优势,以及更合理的API设计。

dx甩opengl几条街
学图形学还是多看看理论书吧,看API没什么意思。

你要知道,至少到vs2008,vs自带的opengl头文件都只是1.1版本的,你这叫人如何用? 微软为了发展DX抑制OpenGL几乎每一本OpenGL书籍都会提到。 -------分割更新-------- 再有就是DX的SDK属于虽然要自己下而且很大但是可以开箱即用,OpenGL就不一样了,glew,glext,glut等等一大堆各式版本的头文件,还要自己保证兼容等等问题……不说了,都是泪
对于从游戏开发者角度而言,OpenGL 曾经是个没人用的东西,Windows / Xbox 上可以用 DirectX,PS3 和 Wii 则又是另外的图像API。

直到iPhone的兴起,OpenGL 居然又活了过来,你看现在连 WebGL 都出现了,有一种统一天下的感觉。
游戏开发者又开始重视 OpenGL 了,当然主要还是 OpenGL ES。

对于显卡公司而言,Windows 上的 D3D 驱动特别重要,会针对各种流行游戏进行定制、优化、hack……至于 OpenGL 驱动,似乎只要满足 CAD 大厂的需求即可,毕竟几乎没有 Windows 上的 OpenGL 游戏啊……

现阶段,从性能考虑(D3D 驱动会特别优化),大型的游戏还是以 D3D 的形式发布,不排除 OpenGL 的优化上去以后也会有大型的桌面 OpenGL 游戏。

对于微软而言,他对于OpenGL的限制非常多,比如WindowsRT,Windows Phone是不支持OpenGL,Windows商店里的应用也必须是DirectX的。

Dota2的OS X和Linux版就是OpenGL的Source引擎做的


近10年来,opengl追赶dx就跟java追赶C#一样。opengl原本是一种设计来做CAD的api,后来被用来搞游戏,火了之后不思进取,造成了计算模型落后到爆炸,后面才慢慢改成了dx11现在的样子的。

而且opengl煞笔还要怪那些A开头公司的编译器。众所周知,一个公司一旦以A开头,那他自主研发的编译器就跟垃圾一样。opengl(和opencl一样)标准要求驱动程序自己去写编译器,就别说linux了,在windows上不同的卡都有互相不兼容的bug。而directx的标准要求驱动程序解释一个指令集的中间语言,不兼容的情况就少了好多,虽然还有,但是已经没什么所谓了。

不过由于底子不好,opengl的api用起来始终没有dx11那么舒服。

P.S.,由于opencl也是一个德行,在windows上的A卡定义一个struct都会导致驱动程序崩溃什么的,让人怎么用啊,只能选cuda或directcompute了。

llvm是apple买的?llvm的创造者在apple工作了快有十年了,而且他还是swift的创造者,他本人已经算apple的一份子了吧。llvm确实是2000年就诞生了,但是走向成熟且大展拳脚则是在加盟apple以后吧



强烈建议初学计算机图形学的玩家不要跳OpenGL这个坑,可能在你编译第一个demo的时候,这辈子就和CG绝缘了。下面就是我的血泪史:

首先,OpenGL自身功能集成度太低,你要么选择大量的附加依赖项,要么写大量的代码。于是各种附加依赖层出不穷,从创建Wnd的glut到windows扩展glew,你都需要了解学习。不过你学习的过程就会惊喜的发现,有一些竟然不更新了,XP available ONLY 哦!剩下那些有更新也是一个丑的不能看的网站(还不如GNU系列的网站,你懂得),只提供源码(由于服务器缘故,下载速度让我还以为被墙了),需要自己编译。很多还是有多层依赖的,这些都需要自己一层一层的下载编译。而且由于C++编译选项千奇百怪,你必须要注意每个库的编译,否则链接错误就是个灾难。而且由于都是自己编译的,拿到别人的电脑上也没法用,别人也需要重新编译,甚至还要修改一些头文件的引用!面对一堆不是你写的,一坨宏和依赖项的C++头文件,去修改,画面真美。而且每换一个地方就要编译20分钟,那酸爽也是绝了。

而且你想写原生的windows窗口,使用Windows Message Loop,而不是用glut的玩具一样的功能,由于没有Help Templates,我当时为了写一个支持多重采样的窗体,看了十几个OpenGL的英文(中文几乎没有开发者!呵呵)wiki和网上教程,才理解了gl绘图上下文的“二次创建”还有颜色模式。最后写出了一个好几百行、N多函数满地宏的main.cpp。当我给别人讲这些的时候,别人都觉得是天书。而一年之后,我也忘了。而DX3D我下载了Sample之后,由于有Templates、Help Tools,我根本不操心窗体创建、Message Loop,可以直奔主题编辑图形,感觉直接到了天堂。

此外,OpenGL里面各种绑定,API接口,让人头晕目眩,一个函数N个参数(而且参数名字长相还特别像,还都是宏,酸爽你懂得),还由于开发者少,生态差,没有一份清晰的文档,也没有特别好的教程。当时为了学习OpenGL,我买了一本红宝书,简直是API Reference + 计算机图形学导论啊,就觉得100块钱买了个砖,根本看不下去。顺带一提,这个绑定机制极其反人类,当时一不小心绑定错了一个ID,各种诡异的现象都出现了,因为模型库都来自于修改第三方,debug用了一天,顺便读了一次3000多行的3D图形导入库,对这一坨坨的递归找BUG,学到的知识简直丰富无比,DEBUG技能点不知道增长了多少。

同样是由于生态差,目前本应该主流使用的GLSL也很难找到资料学习,所以只能用1.1版本的API。然而放弃GLSL就等于回到了那个固定流水的老GPU时代,现代GPU的高效运算、多线程根本用不到了,又回到那个CPU运算为主,命令列表渲染的低效率时代。老师讲解的模型视点变换、透视变换,本来都应该是自己用GLSL实现的,结果都变成了调用现成API,学的东西和练习的东西完全脱节,导致课程实验效果很差,学生们做起来都是十分痛苦。最后图形学的知识几乎成了死记硬背来考试的,学生也没有在实验中获得多少快乐(个别如我这种喜欢自虐的除外。

当然,最大的问题是难以调试!纯C++的OpenGL出BUG时尽管看不到调试的图形反应,但是起码能看到数据反映。但是加入了着色器以后的,如果C++部分编译、运行全部正常,然而却没有任何图像或者不尽如人意的话,恭喜你,锅都在GLSL的部分,而这一部分根本你不能调试,只能对着黑屏发呆思考哪个公式不对,那个数据传递有问题,可能一折腾几个小时就过去了。后来尽管有nSight,但是笔记本双显卡还不能用(默哀~,不知道现在改进了吗?)。这样的调试支持,可以说是要把开发者逼上梁山,不能Debug还玩毛线啊。

网上有人评论,OpenGL你看一本红宝书下去,写出的代码都未必能运行;但是你用DX3D,HelloWorld Sample能跑,基本就可以出程序了。看我想他们易用性差距也就这么大吧。

最后,因为OpenGL的一坨坑,我差点放弃学习计算机图形学,幸好我凭借“毅力”挺了过来,还做出了一个有天空盒、地形、模型导入、粒子系统、反狗牙的小图形引擎,拿了很高的分数。尽管如此,这两天搞毕设,我宁愿用从来没有接触过的DX3D做,也不愿意再碰OpenGL了,毕竟少生点气,多活两年比啥也重要。


我大学的图形学课程教了我OpenGL入门。
如果改成DirectX入门我估计要挂到天荒地老...

OpenGL上手容易:强大的glut封装了很多诸如创建窗口之类的繁琐工作,而且一开始你根本不需要接触复杂的顶点缓冲之类的复杂概念,挨着调用glVertex(),glColor()之类的函数就可以一个一个的将顶点画上去。反观DX,除了从一开始你就得掌握一些windows编程知识用于基本的创建窗口之外,你还必须掌握定点缓冲,一次性传输所有顶点进去才可以让DX进行绘制。作为新手,用OpenGL画一个正方体比DX容易太多... 也更容易建立初始的成就感和兴趣...

事实上老师根本没有讲到顶点缓冲以后的知识。毕竟是计算机图形学,不是OpenGL课... 这些都是我后来自学的。不过还好我学了,DX才能入门..

作为一个两边都接触过的码农来回这个帖子。因为太久没碰GL,可能有误,欢迎指出。代码我就不贴了。

// 为避免机器编译时候出现:SDK中某些值没有被定义的情况,先定义他们。
#ifndef SM_TABLETPC
#define SM_TABLETPC    86
#endif

HTEXTURE tex;//定义一个纹理对象;

3.  调用COM组件的IPicture接口

 

#ifndef SM_MEDIACENTER
#define SM_MEDIACENTER 87
#endif

HEFFECT snd;//声音;

4.  使用MFC的CPictureHolder类

 

// 用于检测注册表项的名称和值名称的常量
const TCHAR *g_szNetfx10RegKeyName = _T(“Software\Microsoft\.NETFramework\Policy\v1.0″);
const TCHAR *g_szNetfx10RegKeyValue = _T(“3705″);
const TCHAR *g_szNetfx10SPxMSIRegKeyName = _T(“Software\Microsoft\Active Setup\Installed Components\{78705f0d-e8db-4b2d-8193-982bdda15ecd}”);
const TCHAR *g_szNetfx10SPxOCMRegKeyName = _T(“Software\Microsoft\Active Setup\Installed Components\{FDC11A6F-17D1-48f9-9EA3-9051954BAA24}”);
const TCHAR *g_szNetfx11RegKeyName = _T(“Software\Microsoft\NET Framework Setup\NDP\v1.1.4322″);
const TCHAR *g_szNetfx20RegKeyName = _T(“Software\Microsoft\NET Framework Setup\NDP\v2.0.50727″);
const TCHAR *g_szNetfx30RegKeyName = _T(“Software\Microsoft\NET Framework Setup\NDP\v3.0\Setup”);
const TCHAR *g_szNetfx30SpRegKeyName = _T(“Software\Microsoft\NET Framework Setup\NDP\v3.0″);
const TCHAR *g_szNetfx30RegValueName = _T(“InstallSuccess”);
const TCHAR *g_szNetfx35RegKeyName = _T(“Software\Microsoft\NET Framework Setup\NDP\v3.5″);
const TCHAR *g_szNetfxStandardRegValueName = _T(“Install”);
const TCHAR *g_szNetfxStandardSPxRegValueName = _T(“SP”);
const TCHAR *g_szNetfxStandardVersionRegValueName = _T(“Version”);

//逻辑函数;
bool FrameFunc()
{
    hge->Effect_PlayEx(snd,50);
    return false;
}
//绘制和渲染函数;
bool RenderFunc()
{
    hge->Gfx_BeginScene();
    hge->Gfx_Clear(0xFF3D59AB);
    spr->Render(0.0,0.0);
    hge->Gfx_EndScene();
    return false;
}

5.  使用GDI+的CImage类(VC6无,从VS2003开始有)

 

// .NET Framework 3.0最终版本的版本信息
const int g_iNetfx30VersionMajor = 3;
const int g_iNetfx30VersionMinor = 0;
const int g_iNetfx30VersionBuild = 4506;
const int g_iNetfx30VersionRevision = 26;

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow
                   )
{
    
//    MessageBox(NULL,"MyHGEDemo","Title",0);
    hge = hgeCreate(HGE_VERSION);//创建hge接口;
    //窗口的宽和高;
    hge->System_SetState(HGE_SCREENWIDTH,screen_width);
    hge->System_SetState(HGE_SCREENHEIGHT,screen_height);
    //设置逻辑函数;
    hge->System_SetState(HGE_FRAMEFUNC,FrameFunc);
    hge->System_SetState(HGE_RENDERFUNC,RenderFunc);
    //窗口标题;
    hge->System_SetState(HGE_TITLE,"我的HGE窗口");
    //使用窗口模式;
    hge->System_SetState(HGE_WINDOWED,true);
    //是否使用声音;
    hge->System_SetState(HGE_USESOUND,true);

测试过的方法有1、3、5。

 

// .NET Framework 3.5最终版本的版本信息
const int g_iNetfx35VersionMajor = 3;
const int g_iNetfx35VersionMinor = 5;
const int g_iNetfx35VersionBuild = 21022;
const int g_iNetfx35VersionRevision = 8;

    hge->System_SetState(HGE_SHOWSPLASH,false);
    
    //初始化成功;
    if (hge->System_Initiate())
    {
        tex = hge->Texture_Load("tanke2.jpg");
        if (!tex)
        {
            MessageBox(NULL,"Load image error!","Error",0);
        }
        spr = new hgeSprite(tex,0,0,535,656);
        
        snd = hge->Effect_Load("020music.mp3");
        if (!snd)
        {
            MessageBox(NULL,"Load sound error!","Error",0);
        }

测试过的格式有BMP/TGA/JPG/GIF/PNG/TIF/ICO/WMF/EMF。

Estereo

 

Estereo是一个开源的双目或者三目立体视觉重建程序,可以在这个地址下载https://sourceforge.net/project/stats/detail.php?group_id=126733&ugn=estereo&type=prdownload
编译需要安装vc.net和directx9.0 sdk,编译时可能需要修改几处地方
1.很多显卡不支持硬件VB,所以修改这里

10bet手机官网 1hr = m_pD3D->CreateDevice(
10bet手机官网 2    D3DADAPTER_DEFAULT,
10bet手机官网 3    D3DDEVTYPE_HAL,
10bet手机官网 4    m_hWnd,
10bet手机官网 5    D3DCREATE_SOFTWARE_VERTEXPROCESSING,//D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE,
10bet手机官网 6    &m_d3dpp, 
10bet手机官网 7    &m_pD3DDevice);

2.有些电脑不能显示三维重建结果,需要修改这里将这些代码移出OnInitdialog

10bet手机官网 8
10bet手机官网 9
10bet手机官网 10CWnd* pParent = GetParent();
10bet手机官网 11  CRect rcParent;
10bet手机官网 12  pParent->GetWindowRect(&rcParent);
10bet手机官网 13  MoveWindow(&rcParent);
10bet手机官网 14
10bet手机官网 15  C3DWindow* p3DWindow= (C3DWindow*)GetDlgItem(IDC_3D_CONTROL);
10bet手机官网 16
10bet手机官网 17  if(p3DWindow)
10bet手机官网 18  {
10bet手机官网 19   CRect rcControl; 
10bet手机官网 20   GetClientRect(&rcControl);
10bet手机官网 21
10bet手机官网 22   rcControl.DeflateRect(10,10,10,10);
10bet手机官网 23   p3DWindow->MoveWindow(&rcControl);
10bet手机官网 24   
10bet手机官网 25   if(((CButton*)GetDlgItem(IDC_CHECK_INITPOS))->GetCheck())
10bet手机官网 26    p3DWindow->SetRegistryKey("3D Reconstruction");//arcball params should be kept separate 
10bet手机官网 27   p3DWindow->Start(false);
10bet手机官网 28
10bet手机官网 29   p3DWindow->CreateVB(m_nPoints,m_pX,m_pY,m_pZ,m_pC,m_pS);
10bet手机官网 30
10bet手机官网 31 }
10bet手机官网 32
10bet手机官网 33

可以自己加上一个按钮,将这些代码加入按钮的响应函数中

 

 

 

 

 

 

 

 opengl贴图程序

//#include <GL/gl.h>
#include <GL/glaux.h> 
#include <glut.h>

//glaux.lib glut32.lib

namespace Test9
{
#include <windows.h> // Header File For Windows
#include <math.h> // Math Library Header File
#include <stdio.h> // Header File For Standard Input/Output
#include <glgl.h> // Header File For The OpenGL32 Library
#include <glglu.h> // Header File For The GLu32 Library
#include <glglaux.h> // Header File For The Glaux Library

HDC hDC=NULL; // Private GDI Device Context
HGLRC hRC=NULL; // Permanent Rendering Context
HWND hWnd=NULL; // Holds Our Window Handle
HINSTANCE hInstance; // Holds The Instance Of The Application

bool keys[256]; // Array Used For The Keyboard Routine
bool active=TRUE; // Window Active Flag Set To TRUE By Default
bool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default
bool blend; // Blending ON/OFF
bool bp; // B Pressed?
bool fp; // F Pressed?

const float piover180 = 0.0174532925f;

GLfloat walkbias = 0;
GLfloat walkbiasangle = 0;
GLfloat rot_x = 0.0f;
GLfloat rot_y=0; // Y Rotation
GLfloat rot_z=0; 
GLfloat g_z=-5.0f; // Depth Into The Screen
GLfloat x=0.0f; // Depth Into The Screen
GLfloat y=0.0f; // Depth Into The Screen

GLuint filter; // Which Filter To Use
GLuint texture[3]; // Storage For 3 Textures

typedef struct tagVERTEX
{
float x, y, z;//3D坐标
float u, v;//纹理坐标
} VERTEX;

typedef struct tagTRIANGLE
{//Triangle三角形结构
VERTEX vertex[3];
} TRIANGLE;

typedef struct tagSECTOR
{
int numtriangles;// Sector中的三角形个数
TRIANGLE* triangle;// 指向三角数组的指针
} SECTOR;

SECTOR sector1; // Our Model Goes Here:

typedef struct{
int numPoints;
VERTEX *vertex;
}MYPOINTS;

MYPOINTS g_pts;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc

void readstr(FILE *f,char *string)
{// 读入一个字符串
do
{
fgets(string, 255, f);

int i1=0,i2=strlen(string),i;
while (string[i1] && (string[i1]==' ' || string[i1]==' '))i1++;
// printf("i1=%d ",i1);
// printf(string);
// while (string[i2]==' ' || string[i2]==' ')i1--;
if(i1>=i2)
continue;
else if(i1>0)
{
for (i=i1;i<i2;i++)
{
string[i-i1]=string[i];
}
string[i2-i1]=0;
// printf(string);
}
} while ((string[0] == '/') || (string[0] == ' '));
return;
}

void SetupWorld()
{// 设置我们的世界
float x, y, z, u, v;
int numtriangles;
FILE *filein;
char oneline[255];
filein = fopen("world.txt", "rt"); // File To Load World Data From
CHECK(filein);

readstr(filein,oneline);
//printf(oneline);
sscanf(oneline, "NUMPOLLIES %d ", &numtriangles);
CHECK(numtriangles>0);

sector1.triangle = new TRIANGLE[numtriangles];
sector1.numtriangles = numtriangles;
for (int loop = 0; loop < numtriangles; loop++)
{
for (int vert = 0; vert < 3; vert++)
{
readstr(filein,oneline);
sscanf(oneline, "%f %f %f %f %f", &x, &y, &z, &u, &v);
sector1.triangle[loop].vertex[vert].x = x;
sector1.triangle[loop].vertex[vert].y = y;
sector1.triangle[loop].vertex[vert].z = z;
sector1.triangle[loop].vertex[vert].u = u;
sector1.triangle[loop].vertex[vert].v = v;
}
}
fclose(filein);
return;
}

//支持定义点和面(三角和四边形)
void SetupWorld2()
{// 设置我们的世界
float x, y, z, u, v;
int numpoints;
FILE *filein;
char oneline[255];
filein = fopen("world2.txt", "rt"); // File To Load World Data From
CHECK(filein);

//读入点
readstr(filein,oneline);
CHECK(1==sscanf(oneline, "NUMPOINTS %d ", &numpoints));
CHECK(numpoints>0);
g_pts.numPoints=numpoints;
g_pts.vertex=new VERTEX[numpoints];

for (int loop = 0; loop < numpoints; loop++)
{
readstr(filein,oneline);
CHECK(5==sscanf(oneline, "%f %f %f %f %f", &x, &y, &z, &u, &v));
g_pts.vertex[loop].x=x;
g_pts.vertex[loop].y=y;
g_pts.vertex[loop].z=z;
g_pts.vertex[loop].u=u;
g_pts.vertex[loop].v=v;
}

//读入面
int numtriangles=0;
readstr(filein,oneline);
CHECK(1==sscanf(oneline, "NUMPTRIANGLES %d ", &numtriangles));
CHECK(numtriangles>0);
sector1.triangle = new TRIANGLE[numtriangles];
sector1.numtriangles = numtriangles;
for ( loop = 0; loop < numtriangles; loop++)
{
int index[3];

readstr(filein,oneline);
CHECK(3==sscanf(oneline, "%d %d %d",index,index+1,index+2));
CHECK(index[0]>=0 && index[0]<g_pts.numPoints);
CHECK(index[1]>=0 && index[1]<g_pts.numPoints);
CHECK(index[2]>=0 && index[2]<g_pts.numPoints);
for (int vert = 0; vert < 3; vert++)
{
sector1.triangle[loop].vertex[vert]= g_pts.vertex[index[vert]];
}
}
fclose(filein);
return;
}

AUX_RGBImageRec *LoadBMP(char *Filename) // Loads A Bitmap Image
{
FILE *File=NULL; // File Handle

if (!Filename) // Make Sure A Filename Was Given
{
return NULL; // If Not Return NULL
}

File=fopen(Filename,"r"); // Check To See If The File Exists

if (File) // Does The File Exist?
{
fclose(File); // Close The Handle
return auxDIBImageLoad(Filename); // Load The Bitmap And Return A Pointer
}
return NULL; // If Load Failed Return NULL
}

int LoadGLTextures() // Load Bitmaps And Convert To Textures
{
int Status=FALSE; // Status Indicator

AUX_RGBImageRec *TextureImage[1]; // Create Storage Space For The Texture

memset(TextureImage,0,sizeof(void *)*1); // Set The Pointer To NULL

// Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
if (TextureImage[0]=LoadBMP("1.bmp"))
{
Status=TRUE; // Set The Status To TRUE

glGenTextures(3, &texture[0]); // Create Three Textures

// Create Nearest Filtered Texture
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);

// Create Linear Filtered Texture
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);

// Create MipMapped Texture
glBindTexture(GL_TEXTURE_2D, texture[2]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
}
if (TextureImage[0]) // If Texture Exists
{
if (TextureImage[0]->data) // If Texture Image Exists
{
free(TextureImage[0]->data); // Free The Texture Image Memory
}

free(TextureImage[0]); // Free The Image Structure
}

return Status; // Return The Status
}

GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
{
if (height==0) // Prevent A Divide By Zero By
{
height=1; // Making Height Equal One
}

glViewport(0,0,width,height); // Reset The Current Viewport

glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix

// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix
}

int InitGL(GLvoid) // All Setup For OpenGL Goes Here
{
if (!LoadGLTextures()) // Jump To Texture Loading Routine
{
return FALSE; // If Texture Didn't Load Return FALSE
}

glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
glBlendFunc(GL_SRC_ALPHA,GL_ONE); // Set The Blending Function For Translucency
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations

SetupWorld2();//建立世界

return TRUE; // Initialization Went OK
}

int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View

GLfloat x_m, y_m, z_m, u_m, v_m;
static DWORD tickCnt=GetTickCount();
int numtriangles;

glTranslatef(x, y, g_z);

#if 1
glRotatef(rot_x,1.0f,0,0);
glRotatef(rot_y,0,1.0f,0);
glRotatef(rot_z,0,0,1.0f);
#else
int norm=sqrt(rot_x*rot_x+rot_y*rot_y+rot_z*rot_z);
int ang_x=0;
int ang_y=0;
int ang_z=0;

if(norm>10)
{
ang_x=rot_x/norm;
ang_y=rot_y/norm;
ang_z=rot_z/norm;
}
else
norm=0;
glRotatef(norm,rot_x,rot_y,rot_z);
#endif

if(GetTickCount()-tickCnt>1000)
{
printf("Trans %8g %8g %8g ",x,y,g_z);
printf("Rot %8g %8g %8g ",rot_x,rot_y,rot_z);
tickCnt=GetTickCount();
}

glBindTexture(GL_TEXTURE_2D, texture[filter]);

numtriangles = sector1.numtriangles;

// Process Each Triangle
for (int loop_m = 0; loop_m < numtriangles; loop_m++)
{
glBegin(GL_TRIANGLES);
glNormal3f( 0.0f, 0.0f, 1.0f);
x_m = sector1.triangle[loop_m].vertex[0].x;
y_m = sector1.triangle[loop_m].vertex[0].y;
z_m = sector1.triangle[loop_m].vertex[0].z;
u_m = sector1.triangle[loop_m].vertex[0].u;
v_m = sector1.triangle[loop_m].vertex[0].v;
glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);

x_m = sector1.triangle[loop_m].vertex[1].x;
y_m = sector1.triangle[loop_m].vertex[1].y;
z_m = sector1.triangle[loop_m].vertex[1].z;
u_m = sector1.triangle[loop_m].vertex[1].u;
v_m = sector1.triangle[loop_m].vertex[1].v;
glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);

x_m = sector1.triangle[loop_m].vertex[2].x;
y_m = sector1.triangle[loop_m].vertex[2].y;
z_m = sector1.triangle[loop_m].vertex[2].z;
u_m = sector1.triangle[loop_m].vertex[2].u;
v_m = sector1.triangle[loop_m].vertex[2].v;
glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);
glEnd();
}
return TRUE; // Everything Went OK
}

GLvoid KillGLWindow(GLvoid) // Properly Kill The Window
{
if (fullscreen) // Are We In Fullscreen Mode?
{
ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
ShowCursor(TRUE); // Show Mouse Pointer
}

if (hRC) // Do We Have A Rendering Context?
{
if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts?
{
MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}

if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?
{
MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
hRC=NULL; // Set RC To NULL
}

if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The DC
{
MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hDC=NULL; // Set DC To NULL
}

if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?
{
MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hWnd=NULL; // Set hWnd To NULL
}

if (!UnregisterClass("OpenGL",hInstance)) // Are We Able To Unregister Class
{
MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hInstance=NULL; // Set hInstance To NULL
}
}

/* This Code Creates Our OpenGL Window. Parameters Are: *
* title - Title To Appear At The Top Of The Window *
* width - Width Of The GL Window Or Fullscreen Mode *
* height - Height Of The GL Window Or Fullscreen Mode *
* bits - Number Of Bits To Use For Color (8/16/24/32) *
* fullscreenflag - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE) */

BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
GLuint PixelFormat; // Holds The Results After Searching For A Match
WNDCLASS wc; // Windows Class Structure
DWORD dwExStyle; // Window Extended Style
DWORD dwStyle; // Window Style
RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
WindowRect.left=(long)0; // Set Left Value To 0
WindowRect.right=(long)width; // Set Right Value To Requested Width
WindowRect.top=(long)0; // Set Top Value To 0
WindowRect.bottom=(long)height; // Set Bottom Value To Requested Height

fullscreen=fullscreenflag; // Set The Global Fullscreen Flag

hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.
wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messages
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = hInstance; // Set The Instance
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer
wc.hbrBackground = NULL; // No Background Required For GL
wc.lpszMenuName = NULL; // We Don't Want A Menu
wc.lpszClassName = "OpenGL"; // Set The Class Name

if (!RegisterClass(&wc)) // Attempt To Register The Window Class
{
MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if (fullscreen) // Attempt Fullscreen Mode?
{
DEVMODE dmScreenSettings; // Device Mode
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.
if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By Your Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen=FALSE; // Windowed Mode Selected. Fullscreen = FALSE
}
else
{
// Pop Up A Message Box Letting User Know The Program Is Closing.
MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
return FALSE; // Return FALSE
}
}
}

if (fullscreen) // Are We Still In Fullscreen Mode?
{
dwExStyle=WS_EX_APPWINDOW; // Window Extended Style
dwStyle=WS_POPUP; // Windows Style
ShowCursor(FALSE); // Hide Mouse Pointer
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style
}

AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size

// Create The Window
if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window
"OpenGL", // Class Name
title, // Window Title
dwStyle | // Defined Window Style
WS_CLIPSIBLINGS | // Required Window Style
WS_CLIPCHILDREN, // Required Window Style
0, 0, // Window Position
WindowRect.right-WindowRect.left, // Calculate Window Width
WindowRect.bottom-WindowRect.top, // Calculate Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL))) // Dont Pass Anything To WM_CREATE
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
bits, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
16, // 16Bit Z-Buffer (Depth Buffer) 
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};

if (!(hDC=GetDC(hWnd))) // Did We Get A Device Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if (!(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if(!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

ShowWindow(hWnd,SW_SHOW); // Show The Window
SetForegroundWindow(hWnd); // Slightly Higher Priority
SetFocus(hWnd); // Sets Keyboard Focus To The Window
ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen

if (!InitGL()) // Initialize Our Newly Created GL Window
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

return TRUE; // Success
}

LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window
UINT uMsg, // Message For This Window
WPARAM wParam, // Additional Message Information
LPARAM lParam) // Additional Message Information
{
switch (uMsg) // Check For Windows Messages
{
case WM_ACTIVATE: // Watch For Window Activate Message
{
if (!HIWORD(wParam)) // Check Minimization State
{
active=TRUE; // Program Is Active
}
else
{
active=FALSE; // Program Is No Longer Active
}

return 0; // Return To The Message Loop
}

case WM_SYSCOMMAND: // Intercept System Commands
{
switch (wParam) // Check System Calls
{
case SC_SCREENSAVE: // Screensaver Trying To Start?
case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
return 0; // Prevent From Happening
}
break; // Exit
}

case WM_CLOSE: // Did We Receive A Close Message?
{
PostQuitMessage(0); // Send A Quit Message
return 0; // Jump Back
}

case WM_KEYDOWN: // Is A Key Being Held Down?
{
keys[wParam] = TRUE; // If So, Mark It As TRUE
return 0; // Jump Back
}

case WM_KEYUP: // Has A Key Been Released?
{
keys[wParam] = FALSE; // If So, Mark It As FALSE
return 0; // Jump Back
}

case WM_SIZE: // Resize The OpenGL Window
{
ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); // LoWord=Width, HiWord=Height
return 0; // Jump Back
}
}

// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

int WINAPI WinMain( HINSTANCE hInstance, // Instance
HINSTANCE hPrevInstance, // Previous Instance
LPSTR lpCmdLine, // Command Line Parameters
int nCmdShow) // Window Show State
{
MSG msg; // Windows Message Structure
BOOL done=FALSE; // Bool Variable To Exit Loop

// Ask The User Which Screen Mode They Prefer
if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
{
fullscreen=FALSE; // Windowed Mode
}

// Create Our OpenGL Window
if (!CreateGLWindow("Lionel Brits & NeHe's 3D World Tutorial",640,480,16,fullscreen))
{
return 0; // Quit If Window Was Not Created
}

while(!done) // Loop That Runs While done=FALSE
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Is There A Message Waiting?
{
if (msg.message==WM_QUIT) // Have We Received A Quit Message?
{
done=TRUE; // If So done=TRUE
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
else // If There Are No Messages
{
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if ((active && !DrawGLScene()) || keys[VK_ESCAPE]) // Active? Was There A Quit Received?
{
done=TRUE; // ESC or DrawGLScene Signalled A Quit
}
else // Not Time To Quit, Update Screen
{
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
if (keys['B'] && !bp)
{
bp=TRUE;
blend=!blend;
if (!blend)
{
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
}
else
{
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
}
}
if (!keys['B'])
{
bp=FALSE;
}

if (keys['F'] && !fp)
{
fp=TRUE;
filter+=1;
if (filter>2)
{
filter=0;
}
}
if (!keys['F'])
{
fp=FALSE;
}

if (keys['R'])//Reset totation matrix
{
rot_x=rot_y=rot_z=0;
}

if (keys['T'])//Reset totation matrix
{
x=y=0;
g_z=-5;
}

if (keys[VK_F1])//pgup
{
x-=0.01f;
}

if (keys[VK_F2])
{
x+=0.01f;
}

if (keys[VK_F3])//pgup
{
y-=0.01f;
}

if (keys[VK_F4])
{
y+=0.01f;
}

if (keys[VK_F5])//pgup
{
g_z-=0.01f;
}

if (keys[VK_F6])
{
g_z+=0.01f;
}

if (keys[VK_PRIOR])//pgup
{
rot_z-=1.0f;
}

if (keys[VK_NEXT])
{
rot_z+=1.0f;
}

if (keys[VK_RIGHT])
{
rot_y -= 1.0f;

}

if (keys[VK_LEFT])
{
rot_y += 1.0f;
}

if (keys[VK_UP])
{
rot_x-= 1.0f;
}

if (keys[VK_DOWN])
{
rot_x+= 1.0f;
}

// if (keys[VK_ESCAPE]) // Is F1 Being Pressed?
// {
// keys[VK_F1]=FALSE; // If So Make Key FALSE
// KillGLWindow(); // Kill Our Current Window
// fullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode
// // Recreate Our OpenGL Window
// if (!CreateGLWindow("Lionel Brits & NeHe's 3D World Tutorial",640,480,16,fullscreen))
// {
// return 0; // Quit If Window Was Not Created
// }
// }
}
}
}

// Shutdown
KillGLWindow(); // Kill The Window
return (msg.wParam); // Exit The Program
}
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;

// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
CString strHello;
strHello.LoadString(IDS_HELLO);
cout << (LPCTSTR)strHello << endl;
}
//Test1::main2();
Test9::WinMain(0,0,0,SW_SHOWNORMAL);
return nRetCode;
}

 

附上测试使用的world2.txt

10bet手机官网 34NUMPOINTS 8
10bet手机官网 350  0  0  0  1
10bet手机官网 361  0  0   0.25  1
10bet手机官网 371  0  1   0.75  1
10bet手机官网 380  0  1 1  1
10bet手机官网 39
10bet手机官网 400  1  0  0 0
10bet手机官网 411  1  0  0.25 0
10bet手机官网 421  1  1  0.75 0
10bet手机官网 430  1  1 1  0
10bet手机官网 44
10bet手机官网 45NUMPTRIANGLES 8
10bet手机官网 460 1 4
10bet手机官网 474 1 5
10bet手机官网 481 2 5
10bet手机官网 492 5 6
10bet手机官网 50
10bet手机官网 512 3 6
10bet手机官网 523 6 7
10bet手机官网 530 3 7
10bet手机官网 540 7 4

mud.bmp

// 函数原型声明
bool CheckNetfxBuildNumber(const TCHAR*, const TCHAR*, const int, const int, const int, const int);
int GetNetfx10SPLevel();
int GetNetfxSPLevel(const TCHAR*, const TCHAR*);
bool IsCurrentOSTabletMedCenter();
bool IsNetfx10Installed();
bool IsNetfx11Installed();
bool IsNetfx20Installed();
bool IsNetfx30Installed();
bool IsNetfx35Installed();
bool RegistryGetValue(HKEY, const TCHAR*, const TCHAR*, DWORD, LPBYTE, DWORD);

        hge->System_Start();
    }     

IPicture接口不支持的格式有:PNG和TIF。

/******************************************************************
Function Name: 判断.NET Framework 1.0是否安装
Description:    Uses the detection method recommended at
[url]]
to determine whether the .NET Framework 1.0 is
installed on the machine
Inputs:        NONE
Results:        .NET Framework 1.0已安装返回TRUE否则返回FALSE
******************************************************************/
bool IsNetfx10Installed()
{
TCHAR szRegValue[MAX_PATH];
return (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx10RegKeyName, g_szNetfx10RegKeyValue, NULL, (LPBYTE)szRegValue, MAX_PATH));
}

    //释放资源;
    hge->Effect_Free(snd);
    hge->Texture_Free(tex);
    delete spr;
    hge->System_Shutdown();
    hge->Release();
    return 0;
}

GDI+支持全部格式。

/******************************************************************
Function Name: 判断.NET Framework 1.1是否安装
Description:    Uses the detection method recommended at
[url]]
to determine whether the .NET Framework 1.1 is
installed on the machine
Inputs:        NONE
Results:        .NET Framework 1.1已安装返回TRUE否则返回FALSE
******************************************************************/
bool IsNetfx11Installed()
{
bool bRetValue = false;
DWORD dwRegValue=0;

 

 

if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx11RegKeyName, g_szNetfxStandardRegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
if (1 == dwRegValue)
bRetValue = true;
}

二、插件的实现(VC6)

return bRetValue;
}

只做了基于DLL的插件实现试验,基于“公共契约”来实现。

/******************************************************************
Function Name: 判断.NET Framework 2.0是否安装
Description:    Uses the detection method recommended at
[url]]
to determine whether the .NET Framework 2.0 is
installed on the machine
Inputs:        NONE
Results:        .NET Framework 2.0已安装返回TRUE否则返回FALSE
******************************************************************/
bool IsNetfx20Installed()
{
bool bRetValue = false;
DWORD dwRegValue=0;

基本方法:

if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx20RegKeyName, g_szNetfxStandardRegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
if (1 == dwRegValue)
bRetValue = true;
}

① 使插件和主程序实现相同的公共基类。

return bRetValue;
}

② 插件只通过公共基类方法与主程序联系,公共基类方法一般为虚函数。

/******************************************************************
Function Name: 判断.NET Framework 3.0是否安装
Description:    Uses the detection method recommended at
[url]]
to determine whether the .NET Framework 3.0 is
installed on the machine
Inputs:        NONE
Results:        .NET Framework 3.0已安装返回TRUE否则返回FALSE
******************************************************************/
bool IsNetfx30Installed()
{
bool bRetValue = false;
DWORD dwRegValue=0;

③ 主程序通过指向公共基类的指针数组保存插件访问地址列表。

// 检查InstallSuccess注册表值存在,等于1
if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx30RegKeyName, g_szNetfx30RegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
if (1 == dwRegValue)
bRetValue = true;
}

④ 主程序根据功能需要遍历插件访问地址列表,通过地址访问插件方法。

//补充核查,检查版本列出的版本号在注册表中,是否已有预发布版的 .NET Framework 3.0 InstallSuccess值。
return (bRetValue && CheckNetfxBuildNumber(g_szNetfx30RegKeyName, g_szNetfxStandardVersionRegValueName, g_iNetfx30VersionMajor, g_iNetfx30VersionMinor, g_iNetfx30VersionBuild, g_iNetfx30VersionRevision));
}

下面以图像显示为例说明插件的实现过程:

/******************************************************************
Function Name: 判断.NET Framework 3.5是否安装
Description:    Uses the detection method recommended at
[url]]
to determine whether the .NET Framework 3.5 is
installed on the machine
Inputs:        NONE
Results:        .NET Framework 3.5已安装返回TRUE否则返回FALSE
******************************************************************/
bool IsNetfx35Installed()
{
bool bRetValue = false;
DWORD dwRegValue=0;

1个主程序Host,4个插件(分别实现对BMP、TGA、JPG、PNG图片的解析)

// 检查安装的注册表值存在,等于1
if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx35RegKeyName, g_szNetfxStandardRegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
if (1 == dwRegValue)
bRetValue = true;
}

1.公共基类

// 补充核查,检查版本列出的版本号在注册表中,是否已有预发布版的 .NET Framework 3.5 InstallSuccess值。
return (bRetValue && CheckNetfxBuildNumber(g_szNetfx35RegKeyName, g_szNetfxStandardVersionRegValueName, g_iNetfx35VersionMajor, g_iNetfx35VersionMinor, g_iNetfx35VersionBuild, g_iNetfx35VersionRevision));
}

// IImageParser is the interface that all image parsers must implement

/******************************************************************
Function Name: 获取.NET Framework 1.0 SP 的版本
Description:    Uses the detection method recommended at
[url]]
to determine what service pack for the
.NET Framework 1.0 is installed on the machine
Inputs:        NONE
Results:        integer representing SP level for .NET Framework 1.0
******************************************************************/
int GetNetfx10SPLevel()
{
TCHAR szRegValue[MAX_PATH];
TCHAR *pszSPLevel = NULL;
int iRetValue = -1;
bool bRegistryRetVal = false;

class IImageParser

//需要检测操作系统上注册表项SP的版本
if (IsCurrentOSTabletMedCenter())
bRegistryRetVal = RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx10SPxOCMRegKeyName, g_szNetfxStandardVersionRegValueName, NULL, (LPBYTE)szRegValue, MAX_PATH);
else
bRegistryRetVal = RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx10SPxMSIRegKeyName, g_szNetfxStandardVersionRegValueName, NULL, (LPBYTE)szRegValue, MAX_PATH);

{

if (bRegistryRetVal)
{
// 格式化SP版本号: #,#,#####,#
pszSPLevel = _tcsrchr(szRegValue, _T(‘,’));
if (NULL != pszSPLevel)
{
// 增量指针跳过逗号
pszSPLevel++;

public:

// 转换值为整数
iRetValue = _tstoi(pszSPLevel);
}
}

     virtual const char * GetID() = 0; // content to be present in host

return iRetValue;
}

     // parses the image file and reads it into a HBITMAP

/******************************************************************
Function Name: 获取.NET Framework SP 的版本
Description:    确定哪些已安装Service Pack的版本。 NET框架使用基于注册表检测方法的记载。 NET Framework的部署指南。
Inputs:        pszNetfxRegKeyName – registry key name to use for detection
pszNetfxRegValueName – registry value to use for detection
Results:        integer representing SP level for .NET Framework
******************************************************************/
int GetNetfxSPLevel(const TCHAR *pszNetfxRegKeyName, const TCHAR *pszNetfxRegValueName)
{
DWORD dwRegValue=0;

     virtual HBITMAP ParseFile( const char *fname ) = 0;

if (RegistryGetValue(HKEY_LOCAL_MACHINE, pszNetfxRegKeyName, pszNetfxRegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
return (int)dwRegValue;
}

     // returns true if the file type is supported

// 从注册表检索 .NET框架未安装或有某种错误的数据
return -1;
}

     virtual bool SupportsType( const char *type ) const = 0;

/******************************************************************
Function Name: 获取.NET Framework 编译版本
Description:    从注册表检索 .NET Framework 的版本号,验证这不是一个预发布版本号
Inputs:        NONE
Results:        true if the build number in the registry is greater
than or equal to the passed in version; false otherwise
******************************************************************/
bool CheckNetfxBuildNumber(const TCHAR *pszNetfxRegKeyName, const TCHAR *pszNetfxRegKeyValue, const int iRequestedVersionMajor, const int iRequestedVersionMinor, const int iRequestedVersionBuild, const int iRequestedVersionRevision)
{
TCHAR szRegValue[MAX_PATH];
TCHAR *pszToken = NULL;
TCHAR *pszNextToken = NULL;
int iVersionPartCounter = 0;
int iRegistryVersionMajor = 0;
int iRegistryVersionMinor = 0;
int iRegistryVersionBuild = 0;
int iRegistryVersionRevision = 0;
bool bRegistryRetVal = false;

};

// 尝试建立一些注册表值
bRegistryRetVal = RegistryGetValue(HKEY_LOCAL_MACHINE, pszNetfxRegKeyName, pszNetfxRegKeyValue, NULL, (LPBYTE)szRegValue, MAX_PATH);

2.插件实现

if (bRegistryRetVal)
{
// 此注册表值应的格式#.#.#####.##.尝试解析4部分版本浏览
pszToken = _tcstok_s(szRegValue, _T(“.”), &pszNextToken);
while (NULL != pszToken)
{
iVersionPartCounter++;

以BMP Parser为例:

switch (iVersionPartCounter)
{
case 1:
// 转换主要版本为整数

① BMPParser.h内容如下:

iRegistryVersionMajor = _tstoi(pszToken);
break;
case 2:
// 转换次要版本值为整数
iRegistryVersionMinor = _tstoi(pszToken);
break;
case 3:
// 转换编译版本值为整数
iRegistryVersionBuild = _tstoi(pszToken);
break;
case 4:
// 转换版本号值为整数
iRegistryVersionRevision = _tstoi(pszToken);
break;
default:
break;

#include <windows.h>

}

#include <stdio.h>

// 获取其它部分的版本号
pszToken = _tcstok_s(NULL, _T(“.”), &pszNextToken);
}
}

#include "ImageParser.h"

// Compare the version number retrieved from the registry with
// the version number of the final release of the .NET Framework 3.0
//从注册表中检索最后发布的 .NET Framework 3.0 的版本号码,比较版本号码
if (iRegistryVersionMajor > iRequestedVersionMajor)
{
return true;
}
else if (iRegistryVersionMajor == iRequestedVersionMajor)
{
if (iRegistryVersionMinor > iRequestedVersionMinor)
{
return true;
}
else if (iRegistryVersionMinor == iRequestedVersionMinor)
{
if (iRegistryVersionBuild > iRequestedVersionBuild)
{
return true;
}
else if (iRegistryVersionBuild == iRequestedVersionBuild)
{
if (iRegistryVersionRevision >= iRequestedVersionRevision)
{
return true;
}
}
}
}

 

// If we get here, the version in the registry must be less than the
// version of the final release of the .NET Framework we are checking,
// so return false
return false;
}

class CBMPParser : public IImageParser 

bool IsCurrentOSTabletMedCenter()
{
// Use GetSystemMetrics to detect if we are on a Tablet PC or Media Center OS
return ( (GetSystemMetrics(SM_TABLETPC) != 0) || (GetSystemMetrics(SM_MEDIACENTER) != 0) );
}

{

/******************************************************************
Function Name: RegistryGetValue
Description:    Get the value of a reg key
Inputs:        HKEY hk – The hk of the key to retrieve
TCHAR *pszKey – Name of the key to retrieve
TCHAR *pszValue – The value that will be retrieved
DWORD dwType – The type of the value that will be retrieved
LPBYTE data – A buffer to save the retrieved data
DWORD dwSize – The size of the data retrieved
Results:        true if successful, false otherwise
******************************************************************/
bool RegistryGetValue(HKEY hk, const TCHAR * pszKey, const TCHAR * pszValue, DWORD dwType, LPBYTE data, DWORD dwSize)
{
HKEY hkOpened;

public:

// Try to open the key
if (RegOpenKeyEx(hk, pszKey, 0, KEY_READ, &hkOpened) != ERROR_SUCCESS)
{
return false;
}

     CBMPParser();

// If the key was opened, try to retrieve the value
if (RegQueryValueEx(hkOpened, pszValue, 0, &dwType, (LPBYTE)data, &dwSize) != ERROR_SUCCESS)
{
RegCloseKey(hkOpened);
return false;
}

     virtual ~CBMPParser();

// Clean up
RegCloseKey(hkOpened);

 

return true;
}

public:

int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR    lpCmdLine,
int      nCmdShow)
{
int iNetfx10SPLevel = -1;
int iNetfx11SPLevel = -1;
int iNetfx20SPLevel = -1;
int iNetfx30SPLevel = -1;
int iNetfx35SPLevel = -1;
TCHAR szMessage[MAX_PATH];

     virtual const char * GetID() { return "BMP";};

// Determine whether or not the .NET Framework
// 1.0, 1.1, 2.0 or 3.0 are installed
bool bNetfx10Installed = IsNetfx10Installed();
bool bNetfx11Installed = IsNetfx11Installed();
bool bNetfx20Installed = IsNetfx20Installed();

     virtual HBITMAP ParseFile( const char *fname );

// The .NET Framework 3.0 is an add-in that installs
// on top of the .NET Framework 2.0. For this version
// check, validate that both 2.0 and 3.0 are installed.
bool bNetfx30Installed = (IsNetfx20Installed() && IsNetfx30Installed());

     virtual bool SupportsType( const char *type ) const;

// The .NET Framework 3.5 is an add-in that installs
// on top of the .NET Framework 2.0 and 3.0. For this version
// check, validate that 2.0, 3.0 and 3.5 are installed.
bool bNetfx35Installed = (IsNetfx20Installed() && IsNetfx30Installed() && IsNetfx35Installed());

    

// If .NET Framework 1.0 is installed, get the
// service pack level
if (bNetfx10Installed)
{
iNetfx10SPLevel = GetNetfx10SPLevel();

private:

if (iNetfx10SPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T(“.NET Framework 1.0 service pack %i is installed.”), iNetfx10SPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T(“.NET Framework 1.0 is installed with no service packs.”));

     HBITMAP CreateBitmap( int width, int height, void **data );

MessageBox(NULL, szMessage, _T(“.NET Framework 1.0″), MB_OK | MB_ICONINFORMATION);
}
else
{
MessageBox(NULL, _T(“.NET Framework 1.0 is not installed.”), _T(“.NET Framework 1.0″), MB_OK | MB_ICONINFORMATION);
}

};

// If .NET Framework 1.1 is installed, get the
// service pack level
if (bNetfx11Installed)
{
iNetfx11SPLevel = GetNetfxSPLevel(g_szNetfx11RegKeyName, g_szNetfxStandardSPxRegValueName);

static CBMPParser g_BMPParser;

if (iNetfx11SPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T(“.NET Framework 1.1 service pack %i is installed.”), iNetfx11SPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T(“.NET Framework 1.1 is installed with no service packs.”));

② BMPParser.cpp的主要内容如下:

MessageBox(NULL, szMessage, _T(“.NET Framework 1.1″), MB_OK | MB_ICONINFORMATION);
}
else
{
MessageBox(NULL, _T(“.NET Framework 1.1 is not installed.”), _T(“.NET Framework 1.1″), MB_OK | MB_ICONINFORMATION);
}

// Creates a bitmap with the specified size

// If .NET Framework 2.0 is installed, get the
// service pack level
if (bNetfx20Installed)
{
iNetfx20SPLevel = GetNetfxSPLevel(g_szNetfx20RegKeyName, g_szNetfxStandardSPxRegValueName);

HBITMAP CBMPParser::CreateBitmap( int width, int height, void **data )

if (iNetfx20SPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T(“.NET Framework 2.0 service pack %i is installed.”), iNetfx20SPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T(“.NET Framework 2.0 is installed with no service packs.”));

{

MessageBox(NULL, szMessage, _T(“.NET Framework 2.0″), MB_OK | MB_ICONINFORMATION);
}
else
{
MessageBox(NULL, _T(“.NET Framework 2.0 is not installed.”), _T(“.NET Framework 2.0″), MB_OK | MB_ICONINFORMATION);
}

     BITMAPINFO bmi={sizeof(BITMAPINFOHEADER),width,height,1,24,0,0,0,0,0,0};

// If .NET Framework 3.0 is installed, get the
// service pack level
if (bNetfx30Installed)
{
iNetfx30SPLevel = GetNetfxSPLevel(g_szNetfx30SpRegKeyName, g_szNetfxStandardSPxRegValueName);

     return CreateDIBSection(NULL,&bmi,DIB_RGB_COLORS,data,0,0);

if (iNetfx30SPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T(“.NET Framework 3.0 service pack %i is installed.”), iNetfx30SPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T(“.NET Framework 3.0 is installed with no service packs.”));

}

MessageBox(NULL, szMessage, _T(“.NET Framework 3.0″), MB_OK | MB_ICONINFORMATION);
}
else
{
MessageBox(NULL, _T(“.NET Framework 3.0 is not installed.”), _T(“.NET Framework 3.0″), MB_OK | MB_ICONINFORMATION);
}

// Parses a BMP file

// If .NET Framework 3.5 is installed, get the
// service pack level
if (bNetfx35Installed)
{
iNetfx35SPLevel = GetNetfxSPLevel(g_szNetfx35RegKeyName, g_szNetfxStandardSPxRegValueName);

HBITMAP CBMPParser::ParseFile( const char *fname )

if (iNetfx35SPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T(“.NET Framework 3.5 service pack %i is installed.”), iNetfx35SPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T(“.NET Framework 3.5 is installed with no service packs.”));

{

MessageBox(NULL, szMessage, _T(“.NET Framework 3.5″), MB_OK | MB_ICONINFORMATION);
}
else
{
MessageBox(NULL, _T(“.NET Framework 3.5 is not installed.”), _T(“.NET Framework 3.5″), MB_OK | MB_ICONINFORMATION);
}

     FILE *f=fopen(fname,"rb");

return 0;
}

     if (!f) return NULL;

    

     BITMAPFILEHEADER bmfh;

     memset(&bmfh,0,sizeof(bmfh));

     fread(&bmfh,sizeof(bmfh),1,f);

     BITMAPINFOHEADER bmih;

     memset(&bmih,0,sizeof(bmih));

     fread(&bmih,sizeof(bmih),1,f);

     int width=bmih.biWidth;

     int height=bmih.biHeight;

    

     if (bmih.biBitCount!=24) {

         // only 24 bit images are supported

         fclose(f);

         return NULL;

     }

    

     // create the HBITMAP

     void *data;

     HBITMAP bitmap=CreateBitmap(width,height,&data);

     if (!bitmap) {

         fclose(f);

         return NULL;

     }

    

     // read the pixels

     int pitch=(width*3+3)&~3;

     fread(data,pitch,height,f);

    

     fclose(f);

     return bitmap;

}

// Notifies the host that the plugin supports the BMP type

bool CBMPParser::SupportsType( const char *type ) const

{

     return stricmp(type,".bmp")==0;

}

// The host calls this function to get access to the image parser

extern "C" __declspec(dllexport) IImageParser *GetParser( void ) { return &g_BMPParser; }

③ 工作机制

Host通过方法查询该插件是否支持“某种格式”,如果支持,而调用方法对图片数据进行解析。解析的结果是包含图像像素数据的HBITMAP对象。如果该插件不支持该格式,则继续查询下一插件。

2.主程序Host的实现

实验采用标准的MFC架构。

① 实现插件管理类

const int MAX_PARSERS=100;

#include <windows.h>

#include <stdio.h>

#include "ImageParser.h"

 

class CImageManager 

{   

public:

   CImageManager();

    virtual ~CImageManager();

 

private:

    // a prototype for the GetParser function

    typedef IImageParser *(*TGetParser)( void );

    

    // a global list with all parsers

    IImageParser *g_Parsers[MAX_PARSERS];

    int g_NumParsers;

    

public:

    // the currently displayed bitmap

    HBITMAP g_Bitmap;

 

public:

    // Adds the parser to the g_Parsers list

    void AddParser( IImageParser *parser );

 

    // Loads all plugins in the same folder as the EXE

    void LoadPlugins( CMenu * menu );

    

    // Loads an image file

    BOOL LoadImage( const char *fname );

};

② 应用程序类CHostApp中定义图像插件管理类

CImageManager* m_imgManager;

③ 框架类CMainFrame中加载插件并实现图片文件拖放

OnCreate()方法中:

((CHostApp*)AfxGetApp())->m_imgManager->LoadPlugins(GetMenu()); //加载插件

DragAcceptFiles(TRUE); //允许拖放

OnDropFiles()响应函数中:

// get the file name

char fname[_MAX_PATH];

DragQueryFile(hDropInfo,0,fname,_MAX_PATH);

DragFinish(hDropInfo);

 

// load the image file

((CHostApp*)AfxGetApp())->m_imgManager->LoadImage(fname);

CRect rect;

GetClientRect(&rect);

InvalidateRect(rect, TRUE);

④ 文档类CHostDoc中OnOpenDocument()方法打开图像,并通过插件类进行加载

((CHostApp*)AfxGetApp())->m_imgManager->LoadImage(lpszPathName);

⑤ 视图类CHostView中OnDraw()方法显示图像

CImageManager* imgManager = ((CHostApp*)AfxGetApp())->m_imgManager;

if (NULL != imgManager && NULL != imgManager->g_Bitmap)

{

     HBITMAP oldBitmap;

     BITMAP bmp;

     CDC memDC;

     CRect rect;

     memDC.CreateCompatibleDC(pDC);

     GetClientRect(&rect);

     oldBitmap = (HBITMAP)memDC.SelectObject(imgManager->g_Bitmap);

     GetObject(imgManager->g_Bitmap, sizeof(bmp), &bmp);

     pDC->BitBlt(0, 0, bmp.bmWidth, bmp.bmHeight, &memDC, 0, 0, SRCCOPY);

     memDC.SelectObject(oldBitmap);

     memDC.DeleteDC();

}

完毕!

 

三、IPicture接口解析图像文件

参见《利用COM组件IPicture读取jpg、gif、bmp图片文件数据和显示图片的两个函数》:

显示图片格式的程序中只需要解析到HBITMAP为止,修改后的函数如下:

HBITMAP CJPGParser::ParseFile( const char *pName )

{

    HDC            hdcTemp; //DC用来保存位图 

    HBITMAP     hbmpTemp;   // 保存临时位图 

    IPicture    *pPicture;  // 定义IPicture Interface 

    OLECHAR     wszPath[MAX_PATH+1]; // 图片的完全路径 

    char        szPath[MAX_PATH+1];  // 图片的完全路径 

    long        lWidth; // 图像宽度 

    long        lHeight;    // 图像高度 

    long        lWidthPixels;    // 图像的宽带(以像素为单位) 

    long        lHeightPixels;   // 图像的高带(以像素为单位) 

 

     strcpy(szPath, pName);  // 把路径拷贝到 szPath

    // 把ASCII码转化为Unicode标准码 

    MultiByteToWideChar(CP_ACP, 0, szPath, -1, wszPath, MAX_PATH);

    HRESULT hr = OleLoadPicturePath(wszPath, 0, 0, 0, IID_IPicture, (void**)&pPicture); 

 

    if(FAILED(hr))  // 如果导入失败 

    { 

        MessageBox (HWND_DESKTOP, "图片导入失败!/n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION); 

        return NULL;

    }  

 

    hdcTemp = CreateCompatibleDC(GetDC(NULL)); // 建立窗口设备描述表  

    if(!hdcTemp)    // 建立失败? 

    { 

        pPicture->Release(); // 释放IPicture 

        MessageBox (HWND_DESKTOP, "图片导入失败!/n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION); 

        return NULL;

    } 

 

    pPicture->get_Width(&lWidth);    // 取得IPicture 宽度 (转换为Pixels格式) 

    lWidthPixels = MulDiv(lWidth, GetDeviceCaps(hdcTemp, LOGPIXELSX), 2540); 

    pPicture->get_Height(&lHeight);  // 取得IPicture 高度 (转换为Pixels格式) 

    lHeightPixels = MulDiv(lHeight, GetDeviceCaps(hdcTemp, LOGPIXELSY), 2540); 

 

    BITMAPINFO  bi = {0};     // 位图的类型 

     void       *pData = 0; // 指向位图Data的指针 

    bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); // 设置结构大小 

    bi.bmiHeader.biBitCount = 32;                // 32 位 

    bi.bmiHeader.biWidth    = lWidthPixels; // 宽度像素值 

    bi.bmiHeader.biHeight   = lHeightPixels;    // 高度像素值  

    bi.bmiHeader.biCompression  = BI_RGB;            // RGB 格式 

    bi.bmiHeader.biPlanes   = 1;                    // 一个位平面 

 

    // 建立一个位图这样我们可以指定颜色和深度 并访问每位的值 

    hbmpTemp = CreateDIBSection(hdcTemp, &bi, DIB_RGB_COLORS, &pData, 0, 0); 

    if(!hbmpTemp)   // 建立失败? 

    { 

        DeleteDC(hdcTemp);   // 删除设备描述表 

        pPicture->Release();   // 释放IPicture 

        MessageBox (HWND_DESKTOP, "图片导入失败!/n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION); 

        return NULL;

    }    

 

    SelectObject(hdcTemp, hbmpTemp); //选择临时DC句柄和临时位图对象 

    // 在位图上绘制IPicture 

    pPicture->Render(hdcTemp, 0, 0, lWidthPixels, lHeightPixels, 0, lHeight, lWidth, -lHeight, 0); 

 

    DeleteDC(hdcTemp);  // 删除设备描述表  

    pPicture->Release(); // 释放 IPicture 

 

     return hbmpTemp;

}

基本原理是建立一个虚拟的HDC,将图绘制到该HDC上即可获得图像像素数据。

 

四、使用GDI+解析图像文件

VC6不支持GDI+,但可以将VS2003以上版的CImage类通过DLL包括后引入VC6。针对上文的图像显示,包装的方法有两种:

1.只用CImage解析图片文件,返回HBITMAP

参见《VC6 CImage 加载jpg png bmp》:。

我的基于VS2008的 DLL的实现代码如下:

① Image2008.h中的代码:

#ifndef AFX_EXT_CLASS

#define AFX_EXT_CLASS __declspec(dllimport)

#endif

extern "C" AFX_EXT_CLASS HBITMAP LoadAtlImage(const char * pszFileName);

② Image2008.cpp中的代码:

#define AFX_EXT_CLASS __declspec(dllexport)

#include "stdafx.h"

#include "Image08.h"

#include <atlimage.h>

#include <atlconv.h>

HBITMAP LoadAtlImage(const char * pszFileName)

{

     CImage img;

     USES_CONVERSION;

     HRESULT hr = img.Load(A2T(pszFileName));

     if (SUCCEEDED(hr))

         return img.Detach();

     else

         return NULL;

}

③ 图片文件解析过程

typedef HBITMAP (*LoadImageFunc)(const char *);

LoadImageFunc funcLoadImage = NULL;

HBITMAP hBitmap = NULL;

char szPath[_MAX_PATH];

GetModuleFileName(NULL,szPath,_MAX_PATH);

*PathFindFileName(szPath) = 0;

strcat(szPath, "//CImage08.dll");

HMODULE hModule=LoadLibrary(szPath);

if(hModule)

{

     funcLoadImage = (LoadImageFunc)GetProcAddress(hModule, "LoadAtlImage");

     if (funcLoadImage)

         hBitmap = funcLoadImage(pName);

     FreeLibrary(hModule);

}

return hBitmap;

2.逐函数包括CImage

参见《VC6如何使用VS2005中的CImage类功能》:

我的基于VS2008的 DLL的实现代码如下:

① Image2008.h中的代码:

#ifndef AFX_EXT_CLASS

#define AFX_EXT_CLASS __declspec(dllimport)

#endif

 

class AFX_EXT_CLASS CImage08

{

private:

     void * m_pImage;   //内部数据

public:

     CImage08(void);

     virtual ~CImage08(void);

public:

     inline HRESULT Load(LPCSTR pszFileName);  //装载图片

     inline BOOL IsNull();  //资源是否存在

     inline BOOL Draw(HDC hDestDC, const RECT& rectDest);    //指定设备和区域画图

     inline operator HBITMAP();  //转换为GDI中的HBITMAP, 从而供GDI中的CDC等类使用

};

② Image2008.cpp中的代码:

#define AFX_EXT_CLASS __declspec(dllexport)

#include "stdafx.h"

#include "Image08.h"

#include <atlimage.h>

#include <atlconv.h>

CImage08::CImage08(void)

{

     m_pImage=NULL;

     m_pImage=new CImage;

}

CImage08::~CImage08(void)

{

     if(m_pImage)

     {

         delete m_pImage;

         m_pImage=NULL;

     }

}

inline HRESULT CImage08::Load( LPCSTR pszFileName )

{

     USES_CONVERSION;

     return ((CImage*)m_pImage)->Load(A2T(pszFileName));

}

inline BOOL CImage08::IsNull()

{

     return ((CImage*)m_pImage)->IsNull();

}

inline BOOL CImage08::Draw( HDC hDestDC, const RECT& rectDest )

{

     return ((CImage*)m_pImage)->Draw(hDestDC,rectDest );

}

inline  CImage08::operator HBITMAP()

{

     return ((CImage*)m_pImage)->operator HBITMAP();

}

使用方法与普通的DLL无异,将编译后的.dll文件、.lib文件、.h文件引入Host主程序即可

③ 图片文件解析过程

CImage08 img;

HRESULT rtl = img.Load(pName);

if (rtl == S_OK)

     return img;

else

     return NULL; 

 

五、结束语

使用的GDI+之后,确实感到VC6真的过时了。GDI+几乎可以打开常见的所有图片文件。VC6几乎打开所有的图片文件都需要编程,费时费力,效果还不一定会好。如果不是万不得已,或者十分怀旧,或者十分偏爱VC6的话,能换还是换个更高点版本的VC吧!

 

参考文献:

1.VC++实现插件编程,

2.Plugin System – an alternative to GetProcAddress and interfaces, 

3.利用COM组件IPicture读取jpg、gif、bmp图片文件数据和显示图片的两个函数,

4.VC6 CImage 加载jpg png bmp,

5.VC6如何使用VS2005中的CImage类功能,

本文由10bet手机官网发布于面向对象,转载请注明出处:在VC6中基于dll开发插件用于各种图片显示,写一个小程序来检测10bet手机官网

上一篇:exe运行问题,选择结构程序设计 下一篇:java得到几天前和几天后时间,DateUtil时间工具类
猜你喜欢
热门排行
精彩图文