posts - 30,  comments - 30,  trackbacks - 26
  2008年11月25日
  1. 准备一张图片,格式为BMP,长宽为64像素、128像素或256像素。
  2. 声明一个变量来存放纹理。
    GLuint texture[1];
  3. 用LoadBMP()载入图片,返回一个指向AUX_RGBImageRec的指针。
    AUX_RGBImageRec* texture_image[1];
    memset(texture_image, 0, sizeof(void*));
    texture_image[0] = LoadBMP(“winxp.bmp”);
  4. 创建一个纹理,并指定纹理的属性。
    glGenTextures(1, &texture[0]);
    glBindTextrue(GL_TEXTURE_2D, texture[0]);
  5. 生成纹理。
    glTexImage2D(GL_TEXTURE_2D, 0, 3, texture_image[0]->sizeX, texture_image[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_image[0]->data;
  6. 设置当图片大于(小于)纹理大小时的显示方式。
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  7. 使纹理有效。
    glEnable(GL_TEXTURE_2D);
  8. 在画的过程中,如果有多个纹理,需要使用glBindTexture(GL_TEXTURE_2D, texture[0])选择纹理。
posted @ 2008-11-25 01:34 彭小虎(Tigerkin) 阅读(87) | 评论 (0)编辑
  2008年11月17日

写了个俄罗斯方块,逻辑算法部分中规中矩,棋盘主要采用二维数组的数据结构,而每种方块样式都是Block类的一个对象,方便扩充;界面部分采用了DialogBox,用GDI画,同时还使用双缓冲技术防止画面闪烁。考虑到可以在RC文件里设计程序界面,所以采用了Dialogbox作为主界面,于是麻烦便来了:DialogBox无法接受WM_KEYDOWN中的VK_UP,VK_DOWN等,也就是说上下左右按键没法用。。试了几种办法,都不行,干脆换成了home,end,page up,page down键。玩的时候很不方便~等我再查查资料再改吧,先把这个有残缺的1.0版本发上来。

程序截图:tetris

下载地址:可执行文件源代码

posted @ 2008-11-17 00:57 彭小虎(Tigerkin) 阅读(91) | 评论 (3)编辑
  2008年10月28日

很久没更新了。。发一个自己写的String类,可以自己指定使用ANSI还是UNICODE。这里下载

class String
{
private:
	wchar_t* wdata;
	char* data;
public:
	CharSet cs;
	String(CharSet _cs = USE_UNICODE, int size = 0);	// 默认使用UNICODE,不分配内存(size为0)
	String(const String& str, CharSet _cs = USE_ORIG);	// 必须是引用
	String(const char* str, CharSet _cs = USE_UNICODE);
	String(const wchar_t* str, CharSet _cs = USE_UNICODE);
	~String();

	// 可以从外部直接获得字符串在内存中的地址(小心使用~~)
	char* AnsiStr();		
	wchar_t* UnicodeStr();

	String& operator =(const String& str);
	String& operator =(const char* str);
	String& operator =(const wchar_t* str);

	String operator +(const String& str);
	String operator +(const char* str);
	String operator +(const wchar_t* str);

	String& operator +=(const String& str);
	String& operator +=(const char* str);
	String& operator +=(const wchar_t* str);
	
	int Find(const String& str);
	int Find(const char* str);
	int Find(const wchar_t* str);

	String SubStr(int start, int length);

	void Swap(String& str);

	int Length() const;
	void Clear();
};
posted @ 2008-10-28 20:37 彭小虎(Tigerkin) 阅读(65) | 评论 (0)编辑
  2008年8月16日

我要在MSDN里搜Windows API DrawText函数,如图:

Google: 第一条就是。

Live Search:  找了半天没找到

posted @ 2008-08-16 12:22 彭小虎(Tigerkin) 阅读(106) | 评论 (1)编辑

以往写Windows程序,用的较多的是Delphi的VCL,MFC用的很少,总觉得不习惯,相比MFC我倒宁愿用清新简单的Windows API。呵呵。于是乎,我萌生了一个想法,自己来封装Windows API。开始动手。。

首先我找了一个比较简单的Window API程序,试着把他转换成面向对象的形式。程序尽管简单,但刚上来一个棘手的问题就出现了。。消息机制的封装。

我们都知道,Windows中比如点击按钮,移动窗口等等的交互操作都是由消息机制来完成的。每做一个动作,例如点击一个按钮,Windows便会产生一个相应的消息,在这里就是BN_CLICKED,假设点击按钮后会弹出一个窗口,里面显示若干文字,而这些点击按钮后产生的效果就需要由我们程序员来编写。体现在Windows API中便是“消息处理函数”,如下:

 

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     
switch (message)
     {
     
case BN_CLICKED:

          
//相关代码
          return 0 ;

     
case WM_DESTROY:
          PostQuitMessage (
0) ;
          
return 0 ;
     }
     
return DefWindowProc (hwnd, message, wParam, lParam) ;
}

 

每次都要写这么多case的确是挺麻烦的,于是我想用面向对象的方法解决他。

 

class MessageMap
{
public:
     
int count;  // 消息映射的数目
      Message* message[10];  // 可以存放10对消息映射
      template <typename T>
     
void Add(MessageType 消息名称, T* 对应的处理函数);  // 增加一对消息映射
};

template 
<typename T>
class Message
{
public:
     MessageType 消息名称;
     T
* 对应的处理函数;
     
void Run()
     {
          对应的处理函数();
     }
};

enum MessageType{}

 

这样做其实是有问题的,请看这一段:

 

class MessageMap
{
public:
     
      Message
* message[10];  // 由于Message是模板类,这里应该提供模板参数。这样就失去了模板的作用。
                                
// 我们使用模板就是为了能让他存储不同的函数指针。
      
};

 

想一想,如何用一个统一的接口来调用不同的函数?对了,那就是多态。

我们可以增加一个抽象的接口类来提供调用接口,而具体实现的类则由他派生。

 

class MessageInterface
{
public:
    MessageType type;
    
virtual ~MessageInterface() {}
    
virtual void Run() = 0;
}
;

template 
<typename T>
class Message : public MessageInterface
{
public:
    T
* classPtr;
    
void (T::* funcPtr)();
    Message(MessageType _type, T
* _classPtr, void (T::* _funcPtr)()) : classPtr(_classPtr), funcPtr(_funcPtr)
    
{
        type 
= _type;
    }

    
virtual void Run()
    
{
        
if (classPtr)
        
{
            (classPtr
->*funcPtr)();        // 注意调用函数指针时括号的用法
        }

    }
    
}
;

class MessageMap
{
public:
    
int count;
    MessageMap()
    
{
        count 
= 0;
        Add(DESTROY, 
this&MessageMap::OnDestroy); 
    }

    MessageInterface
* message[10];
    
void OnDestroy()
    
{
        PostQuitMessage(
0);
    }

    template 
<typename T>
    
void Add(MessageType type, T* classPtr, void (T::* funcPtr)())
    
{
        message[count
++= new Message<T>(type, classPtr, funcPtr);
    }

}
;

 

问题解决了!哈哈,测试成功!

具体的代码在这里,结构什么的还很不完善,仅仅是处理了消息机制而已,当作演示吧。

 

posted @ 2008-08-16 11:23 彭小虎(Tigerkin) 阅读(372) | 评论 (1)编辑
  2008年8月7日

今天接到leader布置的一个任务,从TextBox继承一个新的控件并为其增加一些功能,其中一个功能如下:

Add a property: FormatString, when the text box lost focus, the content will be replace with string.Format(FormatString, actualContent),我在做第二个:“当textbox失去焦点时自动格式化文本”的地方遇到了问题。。。

简单起见,简化成“当textbox失去焦点时改变文本内容”。

一种方法是:

重写OnLeave()方法,如下:

protected override void OnLeave(EventArgs e)
{
        
base.OnLeave(e);
        
this.Text = "Override OnLeave";
}

另一种是给Leave事件增加一个订阅者:

private void NewReceiver(object sender, EventArgs e)
{
        
this.text = "NewReceiver";
        Invalidate();
}

//constructor
public MyTextBox()
{
        
this.Leave += new EventHandler(NewReceiver);
}

经测试,均可运行。

现在,把两段代码和在一起,并注释掉第一种方法:

protected override void OnLeave(EventArgs e)
{
    
base.OnLeave(e);
    
//this.Text = "Override OnLeave";
}

private void NewReceiver(object sender, EventArgs e)
{
    
this.text = "NewReceiver";
    Invalidate();
}

//constuctor
public MyTextBox()
{
    
this.Leave += new EventHandler(NewReceiver);
}

运行程序,测试,显示NewReceiver。

接下来再把base.OnLeave(e)注释掉:

protected override void OnLeave(EventArgs e)
{
    
//base.OnLeave(e);
    
//this.Text = "Override OnLeave";
}

private void NewReceiver(object sender, EventArgs e)
{
    
this.text = "NewReceiver";
    Invalidate();
}

//constuctor
public MyTextBox()
{
    
this.Leave += new EventHandler(NewReceiver);
}

运行,发现文本框失去焦点后不会改变内容,仍未空。由此,第二种方法失效了。为何?我们来看一下base.OnLeave()的内容:

protected virtual void OnLeave(EventArgs e)
{
    EventHandler handler 
= (EventHandler) base.Events[EventLeave];
    
if (handler != null)
    {
        handler(
this, e);
    }
}

原来,注释掉这段以后,handler(this, e)无法得到执行,也就没法激发事件,文本框内容当然也就没法改变了。

 

由此,我猜测,C#的事件触发过程大致是这样的:

文本框失去焦点 --> 触发Leave事件 --> 调用OnLeave()函数(这里是因为什么机制调用的?) --> 调用base.OnLeave() --> 再次触发Leave事件 --> 调用NewReceiver() --> 返回,执行this.text = "Override OnLeave"。

红色字,大家谁知道的,帮我解个惑吧~~

posted @ 2008-08-07 19:22 彭小虎(Tigerkin) 阅读(740) | 评论 (8)编辑
  2008年8月2日
     摘要: 很多东西,不是你不会做,而是你不敢去做。久而久之,庸庸碌碌。。要这么想:有什么东西是天生就会的呢!  阅读全文
posted @ 2008-08-02 17:35 彭小虎(Tigerkin) 阅读(65) | 评论 (1)编辑
  2008年7月30日
     摘要: 一,公钥私钥1,公钥和私钥成对出现2,公开的密钥叫公钥,只有自己知道的叫私钥3,用公钥加密的数据只有对应的私钥可以解密4,用私钥加密的数据只有对应的公钥可以解密5,如果可以用公钥解密,则必然是对应的私钥加的密6,如果可以用私钥解密,则必然是对应的公钥加的密明白了?假设一下,我找了两个数字,一个是1,一个是2。我喜欢2这个数字,就保留起来,不告诉你们,然后我告诉大家,1是我的公钥。我有一个文件,不能...  阅读全文
posted @ 2008-07-30 11:16 彭小虎(Tigerkin) 阅读(926) | 评论 (0)编辑
  2008年3月16日
     摘要: classString{public:String(constchar*str="");~String();String(constString&another){constchar*str=another.m_data;//可以正常访问/**//*省略*/private:char*m_data;};c++里,类的访问权限是class level,不是object level的。访问权限只...  阅读全文
posted @ 2008-03-16 19:29 彭小虎(Tigerkin) 阅读(108) | 评论 (1)编辑
  2008年3月8日
     摘要: 很有用的,所以把它记下来1 CString,int,string,char*之间的转换string 转 CStringCString.format("%s", string.c_str());char 转 CStringCString.format("%s", char*);char 转 stringstring s(char *);string 转 char *char *p = string....  阅读全文
posted @ 2008-03-08 23:50 彭小虎(Tigerkin) 阅读(7284) | 评论 (4)编辑