打算写一个C++程序(1)

 

打算实现一个自己的C++程序,具体思路是:

不应用MFC提供的框架;

一个界面对应一个配置文件;

将界面中的所有控件信息写在配置文件中,通过读取配置文件即可知道界面中所有控件的信息,这样的好处是可以动态的修改界面而不需要修改程序;

配置文件的信息:位置信息,控件类型,控件文本,控件ID,控件主键;

提供界面基类,界面的基类完成创建界面控件。 

 

我现在还不会用C++读取配置文件,所以现在配置文件用文本格式。

1:首先写一个存储控件信息的结构体:

 

struct  ConfigInfo
{
    
int  nLeft;         //  左
     int  nRight;         //  右
     int  nTop;         //  上
     int  nBottom;     //  下
     int  nID;         //  控件ID        
     char   * chType;     //  控件类型
     char   * chText;     //  控件文本
     char   * chKey;     //  控件主键        
};

 

由此可知:配置文件的格式:

主键=左;右;上;下;控件ID;控件类型;控件文本

例如:

ID_BTN_START=1;40;1;20;1;button;六子的按钮

 

2:在写类之前,先设置stdafx.h:

 

#ifndef STDAFX_H_
#define  STDAFX_H_

#include 
< afxwin.h >
#include 
< afxext.h >         
#include 
< afxdisp.h >        
#include 
< afxdtctl.h >         
#include 
< afxcmn.h >         
#include 
< windows.h >

#endif

 

 

3:接着写一个读取配置信息的类:

 

const   int  ITEM_COUNT  =   500 ;             //  文件数目

class  MFCINi  
{
public :
    MFCINi();
    
virtual   ~ MFCINi();

public :
    
/* *------------------------------------------------------------------------------------
    * 名    称:    <Open>
    * 说    明:     <打开配置文件>
    * 参    数:     <MFCINi &ini>:<配置信息对象>
    *                <const CString &strPath>:<配置文件路径>
    * 返    回:    <true:打开成功;false:打开失败>
    *---------------------------------------------------------------------------------------
*/
    
bool  Open(MFCINi  & ini,  const  CString  & strPath);
    
    
/* *------------------------------------------------------------------------------------
    * 名    称:    <Close>
    * 说    明:     <关闭文件,释放占用的内存>
    * 参    数: 
    * 返    回:    
    *---------------------------------------------------------------------------------------
*/
    
void  Close();

    
/* *------------------------------------------------------------------------------------
    * 名    称:    <Read>
    * 说    明:     <根据配置键,取得配置项>
    * 参    数:     <char* item>:<配置键>
    * 返    回:    <读出的配置信息>
    *---------------------------------------------------------------------------------------
*/
    
char *  Read( char *  item);

    
/* *------------------------------------------------------------------------------------
    * 名    称:    <GetAppPath>
    * 说    明:     <取得应用程序的路径(bug路径)>
    * 参    数:     <CString &strAppPath>:<存储取得的路径的字符串>
    * 返    回:    <配置项的值>
    *---------------------------------------------------------------------------------------
*/
    
static   void  GetAppPath(CString  & strAppPath);
    
    
char      ** m_chItems;                 //  INi文件配置项
     char      ** m_chItemValues;             //  项目值
     int         m_nItemCount;                 //  INI文件总配置项数
private :
    FILE    
* m_pf;                         //  INI文件指针
};

 

在读取配置文件的类中,提供一个读取当前程序目录的函数GetAppPath。

实现代码:

 

#include  " stdafx.h "
#include 
" MFCINi.h "

/ /
//  Construction/Destruction
/ /


//  取得应用程序的路径
void  MFCINi::GetAppPath(CString  & strAppPath)
{
    GetModuleFileName(NULL, strAppPath.GetBuffer(MAX_PATH), MAX_PATH);
    strAppPath.ReleaseBuffer();
        
    
int  nLength  =   0 ;    
    
char  ch  =  NULL;
    ch 
=   ' / ' ;    
    nLength 
=  strAppPath.GetLength();
    strAppPath 
=  strAppPath.Left(nLength  -   1 );
    nLength 
=  strAppPath.ReverseFind(ch);
    strAppPath 
=  strAppPath.Left(nLength  +   1 );
}

MFCINi::MFCINi()
{
    m_nItemCount 
=   0 ;
    m_chItems 
=  NULL;
    m_chItemValues 
=  NULL;
    m_pf 
=  NULL;
}

MFCINi::
~ MFCINi()
{
    Close();
}

//  打开文件
bool  MFCINi::Open(MFCINi  & ini,  const  CString  & strPath)
{
    CString strIniPath;
    CString strAppPath;
    MFCINi::GetAppPath(strAppPath);
    strIniPath.Format(
" %s%s " , strAppPath, strPath);

    m_pf 
=  fopen(strIniPath,  " a+ " );
    
if  (m_pf  ==  NULL)
    {
        
return   false ;
    }

    m_chItemValues 
=  ( char ** )malloc(ITEM_COUNT * sizeof ( char ** ));
    m_chItems 
=  ( char ** )malloc(ITEM_COUNT  *   sizeof ( char ** ));

    
for  ( int  i  =   0 ; i  <  ITEM_COUNT; i ++ )
    {
        m_chItemValues[i] 
=  NULL;
        m_chItems[i] 
=  NULL;
    }

    
char  chReading[ 500 ];
    
char   * pchSeparator  =  NULL;
    
while (m_nItemCount  <  ITEM_COUNT)
    {
        
int  nEOF  =  fscanf(m_pf,  " %s " , chReading);
        
if  (nEOF  ==  EOF)
        {
            
//  读取成功
             return   true ;
        }

        pchSeparator 
=  strstr(chReading,  " = " );
        
int  nCharCountName  =  pchSeparator  -  chReading;
        
if  (nCharCountName  <   0 )
        {
            
continue ;
        }

        
int  nCharCountValue  =  strlen(chReading)  -  nCharCountName  -   1 ;
        chReading[nCharCountName] 
=   0 ;

        
//  复制数据
        m_chItems[m_nItemCount]  =  ( char * )malloc(nCharCountName  +   1 );
        strcpy(m_chItems[m_nItemCount], chReading);

        m_chItemValues[m_nItemCount] 
=  ( char * )malloc(nCharCountValue  +   1 );
        strcpy(m_chItemValues[m_nItemCount], chReading 
+  nCharCountName  +   1 );
        m_nItemCount
++ ;
    }

    
return   true ;
}

//  读取配置项
char *  MFCINi::Read( char   * nItem)
{
    
if  (m_nItemCount  ==   0 )
    {
        
return  NULL;
    }
    
    
int  i  =   0 ;
    
while  (strcmp(m_chItems[i], nItem)  !=   0 )
    {
        i
++ ;
        
if  (i  ==  m_nItemCount)
        {
            
return  NULL;
        }
    }

    
return  m_chItemValues[i];
}

void  MFCINi::Close()
{
    
if  (m_pf  !=  NULL)
    {
        fclose(m_pf);
        m_pf 
=  NULL;
    }

    
for  ( int  i  =   0 ; i  <  m_nItemCount; i ++ )
    {
        
//  释放第i个配置项内存
         if  (m_chItems[i]  !=  NULL)
        {
            free(m_chItems[i]);
            m_chItems[i] 
=  NULL;
        }

        
//  释放第i个值内存
         if  (m_chItemValues[i]  !=  NULL)
        {
            free(m_chItemValues[i]);
            m_chItemValues[i] 
=  NULL;
        }
    }

    
//  释放配置项内存
     if  (m_chItems  !=  NULL)
    {
        free(m_chItems);
        m_chItems 
=  NULL;
    }

    
//  释放值内存
     if  (m_chItemValues  !=  NULL)
    {
        free(m_chItemValues);
        m_chItemValues 
=  NULL;
    }

    m_nItemCount 
=   0 ;
}

 

 本来想把GetAppPath函数写成普通函数的,后来考虑到这是个基本函数,所以就把它写成了静态函数。

 4:先把程序运行起来吧,写一个主函数,顺便测测配置类好不好用:

在与debug平行的目录中添加一个配置文件“../NaviIniHR.ini”

#include  " stdafx.h "
#include 
" MFCINi.h "

int  APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine,
                     
int  nCmdShow)
{    
    CString path 
=   " ../NaviIniHR.ini " ;
    MFCINi ini;
    ini.Open(ini, path);
    
char *  chValue  =  ini.Read( " ID_BTN_NAVI_GUIDE " );
    AfxMessageBox(chValue);
    
return   1 ;
}

 

5:设置控件样式结构体:CreateWndStruct

 

struct  CreateWndStruct
{
    
int             nWndType;             //  窗体类型    
    DWORD        dwstyle;             //  窗体样式
    DWORD        dwExStyle;             //  扩展样式
    LPCTSTR        lpszClass;             //  对应类
    LPCTSTR        lpszName;             //  名称
    DWORD        style;                 //  样式
    HWND        hwndParent;
    HMENU        hMenu;
    HINSTANCE    hInstance;
    LPVOID        lpCreateParams;
};

 

 

6:然后设置界面基类,基类名称:CSearchBaseDialog:

因为配置文件信息结构体与控件样式结构体只有该基类用,所以把这两个结构体写在基类中。

 

class  CSearchBaseDialog  
{
struct  ConfigInfo
{
    
int  nLeft;         //  左
     int  nRight;         //  右
     int  nTop;         //  上
     int  nBottom;     //  下
     int  nID;         //  控件ID        
     char   * chType;     //  控件类型
     char   * chText;     //  控件文本
     char   * chKey;     //  控件主键        
};

struct  CreateWndStruct
{
    
int             nWndType;             //  窗体类型    
    DWORD        dwstyle;             //  窗体样式
    DWORD        dwExStyle;             //  扩展样式
    LPCTSTR        lpszClass;             //  对应类
    LPCTSTR        lpszName;             //  名称
    DWORD        style;                 //  样式
    HWND        hwndParent;
    HMENU        hMenu;
    HINSTANCE    hInstance;
    LPVOID        lpCreateParams;
};
public :
    CSearchBaseDialog();
    
virtual   ~ CSearchBaseDialog();

private :    
    
/* *------------------------------------------------------------------------------------
    * 名    称:    <CreateControls>
    * 说    明:     <根据配置信息,创建界面的所有控件>
    * 参    数:     
    * 返    回:    
    *---------------------------------------------------------------------------------------
*/
    
void  CreateControls();

    
/* *------------------------------------------------------------------------------------
    * 名    称:    <CreateControls>
    * 说    明:     <根据信息,创建界面的控件>
    * 参    数:     <char *chKey>:<控件的配置主键>
    *                <char *chValue>:<控件的配置信息>
    * 返    回:    <创建控件的句柄>
    *---------------------------------------------------------------------------------------
*/
    HWND CreateControl(
char   * chKey,  char   * chValue);

    
/* *------------------------------------------------------------------------------------
    * 名    称:    <GetCreateWndStyle>
    * 说    明:     <取得创建控件的样式>
    * 参    数:     <CreateWndStruct &createWndStruct>:<控件样式>
    *                <char *chKey>:<控件的配置主键>
    *                <char *chValue>:<控件的配置信息>
    * 返    回:    
    *---------------------------------------------------------------------------------------
*/
    
void  GetCreateWndStyle(CreateWndStruct  & createWndStruct,  char *  chKey,  char *  chValue);
private :
    CString        m_strFile;            
//  配置文件路径
    HWND         * m_hwndControls;     //  窗体中的控件
    HWND         * m_hWnd;             //  当前句柄
};

 

 实现代码:

 


#include 
" stdafx.h "
#include 
" SearchBaseDialog.h "

#include 
" MFCINi.h "

/ /
//  Construction/Destruction
/ /



CSearchBaseDialog::CSearchBaseDialog()
{
    
* m_hWnd       =  NULL;
    m_strFile 
=   " ../NaviIniHR.ini " ;
}

CSearchBaseDialog::
~ CSearchBaseDialog()
{
        if (m_hwndControls != NULL)
       {
             delete[] m_hwndControls;
       }
}

void  CSearchBaseDialog::CreateControls()
{
    MFCINi ini;
    ini.Open(ini, m_strFile);

    
    m_hwndControls 
=   new  HWND[ini.m_nItemCount];
    
for  ( int  i  =   0 ; i  <  ini.m_nItemCount; i ++ )
    {
        m_hwndControls[i] 
=  CreateControl(ini.m_chItems[i], ini.m_chItemValues[i]);
    }
}

HWND CSearchBaseDialog::CreateControl(
char   * chKey,  char   * chValue)
{
    CreateWndStruct createWndStruct;
    GetCreateWndStyle(createWndStruct, chKey, chValue);

    HWND wnd 
=  CreateWindowEx(
            createWndStruct.dwExStyle,
            createWndStruct.lpszClass,
            createWndStruct.lpszName,
            createWndStruct.style,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            createWndStruct.hwndParent,
            createWndStruct.hMenu,
            createWndStruct.hInstance,
            createWndStruct.lpCreateParams);
    
return  wnd;
}

void  CSearchBaseDialog::GetCreateWndStyle(CreateWndStruct  & createWndStruct,  char   * chKey,  char   * chValue)
{
    ConfigInfo info 
=  { 0 0 0 0 0 "" "" "" };
    info.chKey 
=  chKey;
    sscanf(chValue, (
" %d;%d;%d;%d;%d;%s;%s " ), 
        info.nLeft, info.nRight, info.nTop, info.nBottom, 
        info.nID, info.chType, info.chText);

    createWndStruct.dwExStyle        
=   0 ;
    createWndStruct.lpszClass        
=  TEXT(info.chType);
    createWndStruct.lpszName        
=  TEXT( "" );
    createWndStruct.style            
=  WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_OWNERDRAW;
    createWndStruct.hwndParent        
=   * m_hWnd;
    createWndStruct.hInstance        
=  ::AfxGetResourceHandle();
    createWndStruct.hMenu            
=  NULL;
    createWndStruct.lpCreateParams    
=  NULL;
    createWndStruct.hMenu            
=  (HMENU)info.nID;

    
if  (strcmp(info.chType,  " button " ==   0 )
    {
        createWndStruct.nWndType        
=   1 ;
        createWndStruct.dwstyle            
=   WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_OWNERDRAW;
    }
    
else   if  (strcmp(info.chType,  " static " ==   0 )
    {
        createWndStruct.nWndType        
=    3 ;
        createWndStruct.dwstyle            
=   WS_CHILD | WS_VISIBLE | WS_EX_CLIENTEDGE | WS_BORDER;
    }
    
else   if  (strcmp(info.chType,  " edit " ==   0 )
    {
        createWndStruct.nWndType        
=   2 ;
        createWndStruct.dwstyle            
=   WS_CHILD | WS_VISIBLE | ES_LEFT;
    }
    
else
    {
        createWndStruct.nWndType        
=   1 ;
        createWndStruct.dwstyle            
=   WS_CHILD | WS_VISIBLE | WS_EX_CLIENTEDGE | WS_BORDER;
    }
}

 

本来是没有GetCreateWndStyle函数的,后来发现CreateControl函数太大了,而且即生成控件样式,又创建控件,弄得这个函数的主题很不明确,所以从CreateControl函数中分出了一个专门设置样式的函数CreateWndStruct。

 

本来想把ConfigInfo, CreateWndStruct两个结构体放在实现代码里的,后来由于添加了GetCreateWndStyle函数,需要CreateWndStruct做参数类型,所以把它们放到了声明文件中。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值