2010年5月31日 星期一

Non-Virtual Interface (NVI)

class IuGUI : public IuUnknown
{

public:
    void OnDraw(HDC hDC)
    {
        this->OnOwnerDraw(hDC);
    }

private:
    virtual void OnOwnerDraw(HDC hDC) = 0;

};

class CuGUI :
    public IuGUI
{
public:
    CuGUI(void);
    ~CuGUI(void);

    virtual ULONG Release() 
    { 
        delete this;
        return 0;
    }

private:
    virtual void OnOwnerDraw(HDC hDC);
};

2010年5月24日 星期一

how to using CriticalSection

struct CParam
{
    BOOL bActive;
    int nCount;
    CCriticalSection CriticalSection;

    CParam();
};

CParam::CParam()
:bActive(TRUE)
,nCount(0)
{

}

DWORD WINAPI MyThread(LPVOID lpParameter)
{
    CParam *pParam;
    pParam = (CParam*)lpParameter;
    pParam->bActive = TRUE;

    while(1)
    {
        pParam->CriticalSection.Enter();
        ++pParam->nCount;
        pParam->CriticalSection.Leave();
        Sleep(1);
    }

    pParam->bActive = FALSE;

    ExitThread(0);
}



void InitThread()
{
    HANDLE hThread;
    DWORD ThreadId;

    CParam param;
    hThread = CreateThread(NULL, 0, 
        (LPTHREAD_START_ROUTINE)MyThread, (void*)¶m, 0, &ThreadId);

    while(param.bActive == TRUE)
    {
        param.CriticalSection.Enter();
        Sleep(100);
        cout << param.nCount << "\n";
        param.CriticalSection.Leave();
        
    }

    CloseHandle(hThread);
}


int _tmain(int argc, _TCHAR* argv[])
{
    InitThread();
    return 0;
}

define SaveToSQL interface

class ISaveToSQL {
    function GetField()
    {
        echo "hi... go back to study PHP 3 year!";
    }
}
class cucustom extends ISaveToSQL{
    ....

    function GetField()
    {
        $this->field["name"] = $this->name;
        $this->field["tel"] = $this->tel;
        $this->field["address"] = $this->address;

        return $this->field;
    }
}
class CuModelSave extends model
{
    function insertSaveToSQL(/*ISaveToSQL*/ $ISaveToSQL)
    {
        $this->db->insert($this->table_name, $ISaveToSQL->GetField());
    }
}
class custom_sql extends CuModelSave{
    ...
}

2010年5月16日 星期日

Prototype Pattern -- Load User Define Library

function testUnit_CreateCustom()
    {
        $Custom = $this->cucustom->MyClone();
        echo $this->unit->run($Custom != NULL, "is_TRUE", "Create Custom");
        
        if( $Custom == NULL )
            return;
        
        $Custom->Init("Eric", "1234567", "高興路");
        echo $this->unit->run($Custom->name, "Eric", "name");
        echo $this->unit->run($Custom->tel, "1234567", "tel");
        echo $this->unit->run($Custom->address, "高興路", "address");
        
    }

class cucustom {

    var $name;
    var $tel;
    var $address;

    function cucustom($name = "", $tel = "", $address = "")
    {
        $this->Init($name, $tel, $address);
    }

    function MyClone()
    {
        return new cucustom;
    }

    function Init($name = "", $tel = "", $address = "")
    {
        $this->name = $name;
        $this->tel = $tel;
        $this->address = $address;
    }
}

2010年5月12日 星期三

Create General Object From DLL.

// the GUI is a GUI.DLL

// GUI.h


typedef IuGUI* (*LPFN_CREATEGUI)(void);

GUI_API IuGUI* CreateObject(void);
GUI_API IuGUI* CreateObject(void)
{
    return new CuGUI;
}

// CuGUI

class CuGUI :
    public IuGUI
{
public:
    CuGUI(void);
    ~CuGUI(void);

     virtual ULONG Release() 
     { 
        delete this;
        return 0;
     }

    virtual void OnDraw(HDC hDC);
};

// CGUILoadTest

void CGUILoadTest::testDllCreateObject(void)
{

    LPFN_CREATEGUI lpfnCreateGUI = NULL;

    CuDllManager dllGUI;
    BOOL bResult = dllGUI.LoadLibrary(TEXT("GUI.dll"));
    CPPUNIT_ASSERT( bResult != NULL );

    lpfnCreateGUI = (LPFN_CREATEGUI)dllGUI.GetProcAddress(("CreateObject"));
    CPPUNIT_ASSERT( lpfnCreateGUI != NULL );

    IuGUI *pIuGUI = NULL;

    if( lpfnCreateGUI != NULL )
        pIuGUI = lpfnCreateGUI();

    CPPUNIT_ASSERT( pIuGUI != NULL );

    if( pIuGUI != NULL )
        pIuGUI->Release();

}

2010年5月2日 星期日

filedrive - file upload download

class filedrive extends controller{

    function filedrive()
    {
        parent::controller();
        $this->load->model('filedrive_model','FileDrive',true);
        $this->load->library("cudownload");
        $this->load->library("cuupload");
        $this->culogin->onlogin();
    }

    function index($id="")
    {
        $data["downloadlist"] = "";
        if (empty($id))
                $query = $this->FileDrive->file_query();
        else
                $query = $this->FileDrive->tags_like($id);

        foreach($query->result() as $row){
                $filelist["row"] = $row;
                $data["downloadlist"] .= $this->load->view("downloadlist",$filelist,true);
        }
        $dnTable = $this->load->view("downloadtable",$data,true);
        $viewData["body"] = $dnTable;
        $this->_MainFrame($viewData);
    }

    function upload_form(){
        $tags = $this->FileDrive->get_tags();
        $upForm = array("error"=>"");
        $upForm["active_url"] = "filedrive/upload";
        $upLoadform = $this->cuciload->view("upload_form",$upForm,true);
        $tags = $this->cuciload->view("tags",array("tags"=>$tags,),true);
        $backpage = $this->cuciload->view("backpage",array("goback" => "filedrive"),true);
        $viewData["body"] = $backpage.$upLoadform.$tags;
        $this->_MainFrame($viewData);
    }

    function update_form($id){
        $data["row"] = $this->FileDrive->select_file($id);
        $viewData["body"] = $this->load->view("update_form",$data,true).$this->file_tags();
        $this->_MainFrame($viewData);
    }

    function delete_form($id){
        $data["row"] = $this->FileDrive->select_file($id);
        $viewData["body"] = $this->load->view("delete_form",$data,true);
        $this->_MainFrame($viewData);
    }
    
    function file_tags(){
        $tags = $this->FileDrive->get_tags();
        return $this->cuciload->view("tags",array("tags"=>$tags,),true);
    }

    function update($id){
        $this->FileDrive->update($id);
        redirect("filedrive","location");
    }

    function delete($id){
        $row = $this->FileDrive->select_file($id);
        $this->FileDrive->delete_file($id);
        unlink("./uploads/".$row->file_name.$row->file_ext);
        redirect("filedrive","location");
    }


    function IsUpload($result){
        $data = $this->upload->data();
        $data["true_name"] = $result["true_name"];
        $data["file_date"] = date("Y-m-d");
        $data["file_time"] = date("H:i:s");
        $data["file_tag"] = $this->FileDrive->write_sql($data);
        $data["is_img"]= lang("NO")."</li>";
        if($data["is_image"])
        {
            $data["is_img"] = $this->load->view("is_image",$data,true);
        }

        return $data;
    }

    function Upload()
    {
        if ( empty($_FILES["userfile"]["name"]) )
                redirect("filedrive/upload_form", "location");
        $result = $this->FileDrive->filename();

        $this->cuupload->InitUploadLib_($result["file_name"]);

        if ( ! $this->upload->do_upload())
        {
            $data["body"] = $this->upload->display_errors()."<br>".anchor("filedrive","return file upload!");
        }
        else
        {
            $susess_data = $this->IsUpload($result);
            redirect("filedrive","location");
        }
        $this->_MainFrame($data);
    }

    function _MainFrame($frame)
    {
        $data = $this->_Tag_List();
        $frame["leftmenu"] = $this->load->view("leftmenu",$data,true);
        $frame["submenu"] = $this->load->view("submenu","",true);
        $this->csmainframe->view($frame);
    }

    function _Tag_List(){
        $tags = array();
        $query =$this->FileDrive->get_tags();

        foreach($query->result() as $row){
                $number = $this->FileDrive->count_tags_like($row->id);
                $tags[] = anchor("filedrive/index/".$row->id, $row->tags . " ( ".$number ." ) ");
        }

        $query_all = $this->FileDrive->tags_like("");
        $data["all_num"] = $query_all->num_rows();

        $notags_num = $this->FileDrive->tags_like("null");
        $data["notags_num"] = $notags_num->num_rows();
        $data["tag"] = $tags;
        return $data;
    }

    function download($id){
        $result = $this->FileDrive->download($id);
        $this->cudownload->DownLoadEx($result, "./uploads/");
    }

}


2010年4月22日 星期四

login extends controller

class login extends controller{

    function login()
    {
        parent::controller();
    }

    function index()
    {
        $this->load->view("login");
    }

    function chklogin()
    {
        $this->culogin->login($_POST["account"],$_POST["password"]);
        $this->culogin->islogin();
    }

    function logout(){
        $this->session->unset_userdata("login");
        redirect("main","location");
    }
}

2010年4月21日 星期三

CuLogin -- Login base on CodeIgniter Library

class CuLogin {

    function CuLogin()
    {
        $this->Login_Information();
    }

    function Login_Information(){
        $this->login_account = "useric";
        $this->login_password = "password";
    }

    function chk_login($account,$password){
        if (($account == $this->login_account) && ($password == $this->login_password))
            return true;
        return false;
    }

    function login($account = "",$password = ""){
        $CI = &get_instance();
        $CI->session->set_userdata("login",$this->chk_login($account,$password));
    }

    function islogin(){
        $CI = &get_instance();
        if ($CI->session->userdata("login"))
            redirect("bulletin","location");
        redirect("login","location");
    }

    function onlogin(){
        $CI = &get_instance();
        if (!$CI->session->userdata("login"))
            redirect("main","location");
    }


}



2010年4月16日 星期五

weblink -- view

# delete_form.php
<a href="javascript:history.go(-1)"><?=lang("BACK")?></a> <?=anchor("weblink/delete_link/".$row->id,lang("DELETE"))?>
<table>
    <tr>
        <td><?=lang("LINK").lang("DESCRIPTION")?></td>
        <td><?=$row->link_des?></td>
    </tr>
    <tr>
        <td><?=lang("LINK").lang("WEB")?></td>
        <td>http://<?=$row->weblink?></td>
    </tr>
</table>

# edit_form.php
<?=form_open("weblink/{$action}")?>
<table>
    <tr>
        <td><?=lang("LINK").lang("DESCRIPTION")?></td>
        <td><input type="text" name="link_des" size="40" maxlength="64" value="<?=$row->link_des?>" /></td>
    </tr>
    <tr>
        <td><?=lang("LINK").lang("WEB")?></td>
        <td>http://<input type="text" name="weblink" size="40" maxlength="256" value="<?=$row->weblink?>" /></td>
    </tr>
    <tr>
        <td colspan="2" align="center"><input type="submit" value="<?=lang("SUBMIT")?>"></td>
    </tr>
</table>
</form>


# showlink.php

<table border="1">
    <tr>
        <td width="150"><?=lang("LINK").lang("DESCRIPTION")?></td>
        <td width="250"><?=lang("LINK").lang("WEB")?></td>
        <td width="50"><?=lang("EDIT")?></td>
    </tr>
    <?php foreach($query->result() as $row):?>
    <tr>
        <td><?=anchor_popup("http://".$row->weblink,$row->link_des,$atts)?></td>
        <td>http://<?=$row->weblink?></td>
        <td><?=anchor("weblink/edit_form/".$row->id,lang("EDIT"))?> <?=anchor("weblink/delete_form/".$row->id,lang("DELETE"))?></td>
    </tr>
    <?php endforeach;?>
</table>





# submenu.php

<table border="0">
    <tr>
        <td><?=anchor("weblink",lang("VIEW").lang("LINK"))?></td>
        <td><?=anchor("weblink/insert_link_form",lang("INSERT").lang("LINK"))?></td>
    </tr>
</table>

2010年4月15日 星期四

weblink_sql -- model

class weblink_sql extends model{

    function weblink_sql()
    {
        parent::model();
        $database_table = $this->config->item("database_table_name");
        $this->table_name = $database_table."weblink";
    }

    function load_post()
    {
        return array(
            "link_des" => $_POST["link_des"],
            "weblink" => $_POST["weblink"]
        );
    }

    function select($id = ""){
        if($id != "")
            return $this->db->get_where($this->table_name,array("id"=>$id));
        $this->db->order_by("id","desc");
        return $this->db->get($this->table_name);

    }

    function insert()
    {
        $this->db->insert($this->table_name,$this->load_post());
    }

    function update($id)
    {
        $this->db->where("id",$id);
        $this->db->update($this->table_name,$this->load_post());
    }

    function delete($id){
        $this->db->where("id",$id);
        $this->db->delete($this->table_name);
    }

}


2010年4月12日 星期一

weblink - modify web link

class weblink extends controller{

    function weblink()
    {
        parent::controller();
        $this->culogin->onlogin();
        $this->load->model("weblink_sql","WLINK",TRUE);
    }

    function index()
    {
        $data["atts"] = array("width" => "1024");
        $data["query"] = $this->WLINK->select();
        $frame["body"] = $this->load->view("showlink",$data,TRUE);
        $this->_MainFrame($frame);
    }

    function insert_link_form(){
        $data["row"] = array();
        $data["action"] = "insert_link";
        $frame["body"] = $this->load->view("edit_form",$data,TRUE);
        $this->_MainFrame($frame);
    }

    function edit_form($id){
        $query = $this->WLINK->select($id);
        $data["action"] = "update_link/".$id;
        $data["row"] = $query->row();
        $frame["body"] = $this->load->view("edit_form",$data,TRUE);
        $this->_MainFrame($frame);
    }

    function delete_form($id){
        $query = $this->WLINK->select($id);
        $data["row"] = $query->row();
        $frame["body"] = $this->load->view("delete_form",$data,TRUE);
        $this->_MainFrame($frame);
    }

    function insert_link(){
        $this->WLINK->insert();
        $this->_Redirect();
    }

    function update_link($id){
        $this->WLINK->update($id);
        $this->_Redirect();
    }

    function delete_link($id){
        $this->WLINK->delete($id);
        $this->_Redirect();
    }

    function _Redirect(){
        redirect("weblink","location");
    }

    function _MainFrame($frame = ""){
        $frame["submenu"] = $this->load->view("submenu","",TRUE);
        $frame["leftmenu"] ="";
        $this->cuciload->view("mainframework",$frame);
    }
}



2010年2月24日 星期三

CuGLES

class CuGLES : public CuEGL  
{

public:
    void Ortho(double left, double right, double bottom, double top, double Near, double Far);
    void Frustum( double fovy, double aspect, double zNear, double zFar );
    void Viewport(int x, int y, int width, int height);
#if 0
    void DrawArrays(const void *pvlist, const void *pnvlist, const void *ptclist,int stride, int numvertices);
    void DrawElements(const void *pvlist, const void *pnvlist, const void *ptclist,int stride, int numvertices,
        const void *pfaceindex, int numfaceindex);
#endif
    
    CuGLES();
    virtual ~CuGLES();

};


CuGLES::CuGLES()
{

}

CuGLES::~CuGLES()
{

}

#if 0
void CuGLES::DrawArrays(const void *pvlist, const void *pnvlist, const void *ptclist, int stride, int numvertices)
{

    glTexCoordPointer(2, GL_FIXED, stride, ptclist);
    // setup client states
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);    // setup arrays
    // first the vertices
    glVertexPointer(3, GL_FIXED , stride, pvlist);
    glEnableClientState(GL_VERTEX_ARRAY);


    // next the normals
//  glNormalPointer(GL_SHORT, stride, pnvlist);
    glNormalPointer(GL_FIXED , stride, pnvlist);
    glEnableClientState(GL_NORMAL_ARRAY);

    glDrawArrays(GL_TRIANGLES , 0, numvertices);


    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

}


void CuGLES::DrawElements(const void *pvlist, const void *pnvlist, const void *ptclist,int stride, int numvertices,
    const void *pfaceindex, int numfaceindex)
{

    glTexCoordPointer(2, GL_FIXED, stride, ptclist);
    // setup client states
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);


    // setup arrays
    // first the vertices
    glVertexPointer(3, GL_FIXED , stride, pvlist);
    glEnableClientState(GL_VERTEX_ARRAY);


    // next the normals
    glNormalPointer(GL_FIXED , stride, pnvlist);
    glEnableClientState(GL_NORMAL_ARRAY);

    glDrawElements(GL_TRIANGLES , numfaceindex, GL_UNSIGNED_BYTE , pfaceindex);


    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

}
#endif

void CuGLES::Viewport(int x, int y, int width, int height)
{
    glViewport(x,y,width,height);
}

#define PI_     3.14159265358979323846
void CuGLES::Frustum(double fovy, double aspect, double zNear, double zFar)
{
    // 設定投影
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    float right, left, top, bottom;
    top = zNear * tan(fovy * PI_ / 180.0 / 2 );
    bottom = -top;
    right = top * aspect;
    left = -right;

    glFrustumx(EGL_FixedFromFloat(left), EGL_FixedFromFloat(right),
        EGL_FixedFromFloat(bottom), EGL_FixedFromFloat(top),
        EGL_FixedFromFloat(zNear), EGL_FixedFromFloat(zFar) );

}

void CuGLES::Ortho(double left, double right, double bottom, double top, double Near, double Far)
{

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrthox(
        EGL_FixedFromFloat(left),
        EGL_FixedFromFloat(right),
        EGL_FixedFromFloat(bottom), 
        EGL_FixedFromFloat(top), 
        EGL_FixedFromFloat(Near), 
        EGL_FixedFromFloat(Far));

}


完全不了解為什麼要繼承, 想不起來.

2010年2月23日 星期二

CuEGL

class CuEGL  
{

    int _red_size;
    int _green_size;
    int _bule_size;
    int _alpha_size;

public:

    // 
    void SwapBuffers();


    // 只要有呼叫 Init() 做初始化 就要呼叫 Exit() 
    // 在這裡 解構會自動呼叫
    void Exit();

    // 初始化 EGL
    // Return:  1 有問題初始化失敗   0: 一切正常
    bool Init(NativeWindowType hWnd);

    CuEGL();
    virtual ~CuEGL();

    EGLDisplay  _eglDisplay;
    EGLConfig   _eglConfig;
    EGLSurface  _eglSurface;
    EGLContext  _eglContext;



};

CuEGL::CuEGL()
{

    _eglDisplay = EGL_NO_DISPLAY;
    _eglConfig;
    _eglSurface = EGL_NO_SURFACE;
    _eglContext = EGL_NO_CONTEXT;

    _red_size = 5;
    _green_size = 6;
    _bule_size = 5;
    _alpha_size = 0;


}

CuEGL::~CuEGL()
{

    if( _eglDisplay != EGL_NO_DISPLAY )
        this->Exit();

}


bool CuEGL::Init(NativeWindowType hWnd)
{

    int buffer_size = _red_size + _green_size + _bule_size + _alpha_size;
    EGLint  attrs[] = {
        EGL_ALPHA_SIZE, _alpha_size,
        EGL_RED_SIZE, _red_size,
        EGL_GREEN_SIZE, _green_size,
        EGL_BLUE_SIZE, _bule_size,
        EGL_BUFFER_SIZE, buffer_size,
        EGL_DEPTH_SIZE, 16,
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_NONE};

    EGLint  numConfig;
    LONG        lRet = 1; 

    // NOTE: Theres a bunch of stuff we should be doing to release resources
    //       in the case of failure that we're not bothering with atm

    HDC hdc = GetWindowDC((HWND)hWnd);

    // Get the display device


    _eglDisplay = eglGetDisplay(hdc);

    Assert( _eglDisplay != EGL_NO_DISPLAY, L"CuEGL::Init:\n _eglDisplay == EGL_NO_DISPLAY");

    // Initialize the display
    if (!eglInitialize(_eglDisplay, NULL, NULL))
        {  
            Assert(0, L"CuEGL::Init:\n can't Initialize egl");
            return lRet;

        }

    // Obtain the first configuration with a depth buffer
    if (!eglChooseConfig(_eglDisplay, attrs, &_eglConfig, 1, &numConfig))
        { 
            Assert(0, L"CuEGL::Init:\n can't ChooseConfig");
            return lRet; 
        }

    // Create a surface for the main window
    _eglSurface = eglCreateWindowSurface(_eglDisplay, _eglConfig, (NativeWindowType)hWnd, NULL);
    Assert( _eglSurface != EGL_NO_SURFACE, L"CuEGL::Init:\n _eglSurface == EGL_NO_SURFACE");

    // Create an OpenGL ES context
    _eglContext = eglCreateContext(_eglDisplay, _eglConfig, EGL_NO_CONTEXT, NULL);
    Assert( _eglContext != EGL_NO_CONTEXT, L"CuEGL::Init:\n _eglContext == EGL_NO_CONTEXT");


    // Make the context and surface current
    if (!eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _eglContext))
        {  
            Assert(0, L"CuEGL::Init:\n can't MakeCurrent");
            return lRet; 
        }

    return 0;

}

void CuEGL::Exit()
{

    // Set the current context to nothing
    eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);

    // Free any EGL contexts; should be called per context created
    eglDestroyContext(_eglDisplay, _eglContext);

    // Free any EGL surfaces; should be called per surface created
    eglDestroySurface(_eglDisplay, _eglSurface);

    // Terminate any EGL displays; should be called per display initialized
    eglTerminate(_eglDisplay); 

}

void CuEGL::SwapBuffers()
{

    eglSwapBuffers(_eglDisplay, _eglSurface);

}


好舊的碼了~ 如果有更新會在加上去

2010年2月19日 星期五

CuGPSDevice

class CuGPSDevice : public CuPort  
{
    CuFile m_LogFile;
    CuFile m_CheckLogFile;
    CuFile m_CheckErrorLogFile;
    CuFile m_Error_Message_File;


    DWORD m_dReadDataBufferSize;
    DWORD m_dReadDataBuffseIndex;
    BYTE *m_pReadDataBuffer;

    bool _writeFileCheck(CuFile &File, void *pData, int nSize);

public:
    BOOL CheckReadData(BYTE* pReadData);
    virtual void OnWrite(BYTE *pByte, int nSize);
    virtual void OnRead(BYTE *pByte, int nSize);
    CuGPSDevice();
    virtual ~CuGPSDevice();

};




//

CuGPSDevice::CuGPSDevice()
:m_dReadDataBufferSize(1024)
,m_dReadDataBuffseIndex(0)
,m_pReadDataBuffer(NULL)
{

    m_pReadDataBuffer = new BYTE[m_dReadDataBufferSize];

    CuModuleFile mf;
    wstring strLogFile = mf.GetModuleFileName(L"GPS_Log.txt");
    m_LogFile.Open(strLogFile, L"w");


    strLogFile = mf.GetModuleFileName(L"GPS_Check_Log.txt");
    m_CheckLogFile.Open(strLogFile, L"w");

    strLogFile = mf.GetModuleFileName(L"GPS_Check_Error_Log.txt");
    m_CheckErrorLogFile.Open(strLogFile, L"w");


    strLogFile = mf.GetModuleFileName(L"GPS_Error_Message_Log.txt");
    m_Error_Message_File.Open(strLogFile, L"w");
    


}

CuGPSDevice::~CuGPSDevice()
{

}
void CuGPSDevice::OnWrite(BYTE *pByte, int nSize)
{

    unsigned char checksum = 0 ;
    for(int i=0 ; i < nSize; i++)
    {
        checksum ^= pByte[i];
    }
    
    char strCheckSum[2];

    sprintf( strCheckSum, "%x", checksum);
    char pSendStr[2048];
    memset(pSendStr, 0, 2048);

    ::strcat(pSendStr, "$");
    ::strcat(pSendStr, (char*)pByte);

    ::strcat(pSendStr, "*");
    ::strcat(pSendStr, strCheckSum);
    ::strcat(pSendStr, "\x0d");
    ::strcat(pSendStr, "\x0a");
        
    CuPort::OnWrite((BYTE*)pSendStr, strlen(pSendStr));

}

void CuGPSDevice::OnRead(BYTE *pByte, int nSize)
{

    for( int i = 0 ; i < nSize ; i++ )
    {

    
        if( pByte[i] == 0x0a )
        {
            m_pReadDataBuffer[m_dReadDataBuffseIndex++] = pByte[i];
            if( CheckReadData( m_pReadDataBuffer) )
                _writeFileCheck(m_CheckLogFile, (void*)m_pReadDataBuffer , m_dReadDataBuffseIndex);
                m_CheckLogFile.Write(()m_pReadDataBuffer, m_dReadDataBuffseIndex);
            else
                _writeFileCheck(m_CheckErrorLogFile, (void*)m_pReadDataBuffer , m_dReadDataBuffseIndex);
                m_CheckErrorLogFile.Write((void*)m_pReadDataBuffer, m_dReadDataBuffseIndex);


            memset(m_pReadDataBuffer, 0, m_dReadDataBuffseIndex);
            m_dReadDataBuffseIndex = 0;
            continue;
        }

        m_pReadDataBuffer[m_dReadDataBuffseIndex++] = pByte[i];


    }

    {
        m_LogFile.Write((void*)pByte, nSize);
        _writeFileCheck(m_LogFile, (void*)pByte , nSize);
    }


}

BOOL CuGPSDevice::CheckReadData(BYTE* pReadData)
{
    int nSize;
    nSize = strlen((char*)pReadData);

    unsigned char checksumtemp;

    TCHAR checkstr[3];
    checkstr[0] = pReadData[ nSize - 4 ];
    checkstr[1] = pReadData[ nSize - 3 ];
    checkstr[2] = 0;

    swscanf(checkstr, L"%x", &checksumtemp);

    unsigned char checksum = 0 ;
    checksum = 0;
    for(int i=1 ; i < nSize - 5 ; i++)
    {
        checksum ^= pReadData[i];
    }

    return checksum == checksumtemp ? TRUE : FALSE;

}

bool CuGPSDevice::_writeFileCheck(CuFile &File, void *pData, int nSize)
{
    static int nWriteFileResult = 0;
    nWriteFileResult = File.Write(pData, nSize);
    
    bool bResult = (nWriteFileResult == nSize);

    if( !bResult )
    {
        MessageBox(NULL, L"WriteFileError", L"WriteFileError", MB_OK);
        m_Error_Message_File.Write(pData, nSize);
    }
    return bResult;
}

2010年2月18日 星期四

CuImageLoaderBMP



//

class CuImageLoaderBMP : public IuImageLoaderBMP  
{


public:
    CuImageLoaderBMP();
    virtual ~CuImageLoaderBMP();

    //////////////////////////////////////////////////////////////////
    // IuUnknown 公開虛擬界面 
    virtual ULONG Release();

    //////////////////////////////////////////////////////////////////
    // IuImageLoader 公開虛擬界面 
    virtual BOOL LoadFile(IuImageEx *pImageEx, LPCTSTR lpszResourceName);

    enum BMPFORMAT { BMP1555, BMP565};

    void SetBmpFormat(BMPFORMAT bmpFormat);

private:

    BOOL _Load565Bmp(BYTE * pbits);
    BOOL _Load1555Bmp(BYTE * pbits);


//  BOOL _Load565Bmp16(BYTE * pbits);
    BOOL _Load565Bmp24(BYTE * pbits);


    BOOL _Load1555Bmp24(BYTE * ptr);
    BOOL _Load1555Bmp16(BYTE * ptr);
    BOOL _Load1555Bmp8(BYTE * ptr);

private:

    IuImageEx *m_tempImageEx;

    BMPFORMAT m_bmpFormat;
    BITMAPFILEHEADER m_bmfh;
    BITMAPINFOHEADER *m_pInfo;


};


//


CuImageLoaderBMP::CuImageLoaderBMP()
:m_bmpFormat(BMP1555)
,m_pInfo(NULL)
{

}

CuImageLoaderBMP::~CuImageLoaderBMP()
{
    delete [] m_pInfo;
}

ULONG CuImageLoaderBMP::Release()
{
    delete this;
    return 0;
}

void CuImageLoaderBMP::SetBmpFormat(BMPFORMAT bmpFormat)
{
    m_bmpFormat = bmpFormat;
}


BOOL CuImageLoaderBMP::LoadFile(IuImageEx *pImageEx, LPCTSTR lpszResourceName)
{

    delete [] m_pInfo;
    m_pInfo = NULL;

    m_tempImageEx = pImageEx;

    // 需要 Bits 只支援 24 & 16 BIT bmp 圖
    /////////////////////////////////////////////////////////////////////////////////////////////
//  BITMAPINFOHEADER *pInfo = NULL;
    BYTE *pbits;

    CuFile File; 

    if( !File.Open(lpszResourceName, L"rb") )
    {
        Assert(0, L"CuBitmap::LoadFile /n can't open the file");
        return FALSE;
    }


    DWORD readed;
//  BITMAPFILEHEADER bmfh;


    int size = File.GetFileSize();
    if( size > sizeof(BITMAPFILEHEADER) )
    {

        //ReadFile( hfile, &m_bmfh, sizeof(BITMAPFILEHEADER), &readed, 0 );
        readed = File.Read( &m_bmfh,  sizeof(BITMAPFILEHEADER) );

        if(( readed == sizeof(BITMAPFILEHEADER) ) && ( m_bmfh.bfType == 0x4d42 ))
        {

            m_pInfo = (BITMAPINFOHEADER*)(new BYTE[ size - sizeof(BITMAPFILEHEADER) ]);

            Assert(m_pInfo, L"CuBitmap::LoadFile /n not enough memory.");

            File.Read(  m_pInfo, size - sizeof(BITMAPFILEHEADER) );

            // the pInfo type is BITMAPINFOHEADER, 
            // if pInfo add 1 that mean pInfo jump sizeof(BITMAPINFOHEADER)
            pbits = (BYTE*)(m_pInfo+1);

        }
        else
        {
            return FALSE;
        }


    }

    // use Create allocate memory   
    pImageEx->Create(m_pInfo->biWidth, m_pInfo->biHeight, 16);

//  WORD &biBitCount = m_pInfo->biBitCount;

    BOOL bResult = false;

    switch( m_bmpFormat )
    {
    case BMP1555:
        return _Load1555Bmp(pbits);
        break;
    case BMP565:
        return _Load565Bmp(pbits);
        break;
    
    }

    delete [] m_pInfo;
    m_pInfo = NULL;

    return bResult;

}
BOOL CuImageLoaderBMP::_Load565Bmp(BYTE * pbits)
{
    BOOL bResult = false;

    switch( m_pInfo->biBitCount )
    {
    case 24:
        bResult = this->_Load565Bmp24(pbits);
        break;
    case 16:
//      bResult = this->_Load565Bmp16(pbits);
        break;
    case 8:
//      bResult = this->_Load565Bmp8(pbits);
        break;
    default:
        {
            Assert(0, L"CuBitmap::LoadFile /n biBitCount not support.");
        }
        break;
    }

    return bResult;
}
// 
// BOOL CuImageLoaderBMP::_Load565Bmp16(BYTE * pbits)
// {
//  return FALSE;
// }

BOOL CuImageLoaderBMP::_Load565Bmp24(BYTE * pbits)
{

    int nSrcTotalByte = m_tempImageEx->Width() * m_tempImageEx->Height() * 3;
    int nDescTotalByte = m_tempImageEx->Width() * m_tempImageEx->Height() * 2;


    // our copy pointer
    WORD *ptr = (WORD *)m_tempImageEx->Data();

    BYTE r, g, b;

    // Convert From BGR To RGB Format And Copy over
    for( long i = 0; i < nSrcTotalByte; i += 3 ) // Loop Through All Of The Pixels
    {

        BYTE* pPixel=&pbits[i];                 // Grab The Current Pixel

        r = pPixel[2];//br;                                 // copy red
        g = pPixel[1];//bg;                                 // copy green
        b = pPixel[0];//bb;                                 // copy blue

        *(ptr++) = (WORD)( ( r >> 3 << 11) | 
            ( g >> 2 << 5) | 
            ( b >> 3 ) );

    }

    return TRUE;

}


BOOL CuImageLoaderBMP::_Load1555Bmp(BYTE * pbits)
{
    BOOL bResult = false;

    switch( m_pInfo->biBitCount )
    {
    case 24:
        bResult = this->_Load1555Bmp24(pbits);
        break;
    case 16:
        bResult = this->_Load1555Bmp16(pbits);
        break;
    case 8:
        bResult = this->_Load1555Bmp8(pbits);
        break;
    default:
        {
            Assert(0, L"CuBitmap::LoadFile /n biBitCount not support.");
        }
        break;
    }

    return bResult;
}

BOOL CuImageLoaderBMP::_Load1555Bmp8(BYTE * pbits)
{
    int nSrcTotalByte = m_tempImageEx->Width() * m_tempImageEx->Height();
    int nDescTotalByte = m_tempImageEx->Width() * m_tempImageEx->Height() * 2;


    RGBQUAD *pPalette = (RGBQUAD*)(pbits);

    pbits += m_bmfh.bfOffBits - sizeof(BITMAPFILEHEADER) - sizeof(BITMAPINFOHEADER);

    // 來源圖 做 4byte 對齊
    int nSrcJumpByte = 4 - (m_tempImageEx->Width() % 4);
    if( nSrcJumpByte == 4 )
        nSrcJumpByte = 0;

    int nDescJumpByte = 2 - ( (m_tempImageEx->Width() ) % 2 );
    if( nDescJumpByte == 2 )
        nDescJumpByte = 0;

//  nDescJumpByte = 1;


    // our copy pointer
    WORD *ptr = (WORD *)m_tempImageEx->Data();//_bits;

//  BYTE r, g, b;

    // Convert From BGR To RGB Format And Copy over
    //for( long i = 0; i < nSrcTotalByte; i += 1 )   // Loop Through All Of The Pixels

    int i = 0;
    for( int nHeight = 0 ; nHeight < m_tempImageEx->Height() ; nHeight += 1 )
    {
        for( int nWidth = 0 ; nWidth < m_tempImageEx->Width() ; nWidth += 1)
        {

            int nColorIndex = pbits[i++];                   // Grab The Current Pixel
            RGBQUAD Color = pPalette[nColorIndex];

            *(ptr++) = (WORD)( ( Color.rgbRed >> 3 << 10) | 
                                ( Color.rgbGreen >> 3 << 5) | 
                                ( Color.rgbBlue >> 3 ) );

        }
        i += nSrcJumpByte; 
        ptr += nDescJumpByte;

    }



    return TRUE;
}


BOOL CuImageLoaderBMP::_Load1555Bmp16(BYTE * pbits)
{

    int nTotalByte = m_tempImageEx->Width() * m_tempImageEx->Height() * 2;
    BYTE *pData = m_tempImageEx->Data();
    memcpy( pData, pbits, nTotalByte);
    return TRUE;

}

BOOL CuImageLoaderBMP::_Load1555Bmp24(BYTE * pbits)
{

        int nSrcTotalByte = m_tempImageEx->Width() * m_tempImageEx->Height() * 3;
        int nDescTotalByte = m_tempImageEx->Width() * m_tempImageEx->Height() * 2;


        // our copy pointer
        WORD *ptr = (WORD *)m_tempImageEx->Data();

        BYTE r, g, b;

        // Convert From BGR To RGB Format And Copy over
        for( long i = 0; i < nSrcTotalByte; i += 3 ) // Loop Through All Of The Pixels
        {

            BYTE* pPixel=&pbits[i];                 // Grab The Current Pixel
            
            r = pPixel[2];//br;                                 // copy red
            g = pPixel[1];//bg;                                 // copy green
            b = pPixel[0];//bb;                                 // copy blue

            *(ptr++) = (WORD)( ( r >> 3 << 10) | 
                                      ( g >> 3 << 5) | 
                                      ( b >> 3 ) );

        }

    return TRUE;

}


功能複合的太多就會像上面這樣, 整個看起來好像很好用, 但真的要改的時後, 會有點頭大的感覺

2010年2月17日 星期三

CuResetSystemIdleTimer


//


class CuResetSystemIdleTimer
{
    TuWinTimer<CuResetSystemIdleTimer> m_WinTimer;

public:
    CuResetSystemIdleTimer();
    virtual ~CuResetSystemIdleTimer();
    BOOL Init(HANDLE hParent);
    void OnTimeOut();

};


//


CuResetSystemIdleTimer::CuResetSystemIdleTimer()
{

}

CuResetSystemIdleTimer::~CuResetSystemIdleTimer()
{

}

BOOL CuResetSystemIdleTimer::Init(HANDLE hParent)
{
    OnTimeOut();

    m_WinTimer.Init(30000);
    m_WinTimer.CombineElement(this, &CuResetSystemIdleTimer::OnTimeOut, (HWND)hParent);
    m_WinTimer.OnStardTime();
    return TRUE;
}

void CuResetSystemIdleTimer::OnTimeOut()
{
    keybd_event(VK_F24 , 0, KEYEVENTF_SILENT, 0);    
    keybd_event(VK_F24 , 0, KEYEVENTF_SILENT | KEYEVENTF_KEYUP, 0);
}

猜看看這個是幹嘛的!

2010年2月16日 星期二

CuHtmlGeneric

//


class CuHtmlGeneric
{
    function OnHTML()
    {
        
    }   
}



class CuHTMLString extends CuHtmlGeneric
{
    var $m_string;
    
    function CuHTMLString()
    {
        $this->m_string = "";
    }
    
    function OnAdd($str)
    {
        $this->m_string .= $str;
    }
    
    function OnHTML()
    {
        return $this->m_string;
    }
}

class CuWebControl extends CuHtmlGeneric
{
    var $Attribute;
    
    function CuWebControl()
    {
        $this->Attribute = array();
    }
    
    
    function __set($member, $val){
        $this->Attribute[$member] = $val;
    }
    
    function Set($member, $val)
    {
        $this->__set($member, $val);
    }
    
    function __get($member)
    {
        return $this->Attribute[$member];
    }
    
    function Get($member)
    {
        return $this->__get($member);
    }
    
    function Remove($member)
    {
        $Attribute = $this->Attribute[$member];
        unset($this->Attribute[$member]);
        return $Attribute;
    }
    
    function MakeAttribute()
    {
        foreach($this->Attribute as $key => $value)
        {
            if( $value != "" )
                $str = "$key=\"$value\" ";
            else
                $str = "$key ";
            
            $html .= $str;
        }
        
        return $html;
    }
    
    
    function OnHTML()
    {
        $html = "<" . $this->MakeAttribute() . ">";
        return $html;
    }
    
}

/************************************************
* 類別名稱: CuHTMLAnchor
* 類別說明: 將HTML 的 連結控制項 Tag <a>
************************************************/
class CuHTMLAnchor extends CuWebControl
{
    
    function CuHTMLAnchor()
    {
        //CuHTMLAnchor
    }
    
    function OnHTML()
    {
        
        $value = $this->Remove("value");
        
        $html = "<" . $this->MakeAttribute() . ">" . $value . "</a>";
        
        return $html;
    }
}

支援 CuPage 的相關類別, 控制項類別, 組合字串類別, 方便用來操做HTML組裝

2010年2月15日 星期一

CuPage

// Task.form.html
<table><tr><td>
    <form method="POST" action="">
<input type="hidden" name="msg" value="#?msg?#">

    主旨:<input type="text" name="title" size="80"></p>
    <p>內容:<br>
    <textarea rows="5" name="description" cols="80"></textarea></p>
    <p><input type="submit" value="送出" name="B1"><input type="reset" value="重新設定" name="B2"></p>
    </form>
</td></tr></table>



//

class CuTestTaskForm extends CuPage 
{
    function OnProcess()
    {
        $this->title->Set("value", "哦哦更爽的");
        $this->msg->Set("value", "這樣行嗎?");
    }
    
}

$page = new CuTestTaskForm;

$filename = "resource/Task.form.html";
$page->LoadFile($filename);


$nIndex = $page->GetObjectIndex("msg");
$this->debug->debug($nIndex, "msg nIndex");
$this->assertTrue($nIndex == 5, "msg nIndex from CuPageGetObjectIndex");

$msg = $page->GetObject("msg");
$msg->Set("value", "抓出來的是考備版");
$this->debug->debug($msg, "CuPage::GetObject 抓出來的是考備版");
$page->SetObject($msg); // 再蓋回去囉
$this->debug->innerText($page->OnHTML(), "CuPage->SetObject 再蓋回去囉");

$page->OnProcess();
$this->debug->innerText($page->OnHTML(), "from CuPage::OnHTML");


// CuPage.php


/************************************************
* 類別名稱: CuPage
* 類別說明: 將HTML 的 form 載入後轉為PHP控制物件 CuWebControl
* 現在只支援 <INPUT >
************************************************/
class CuPage
{
    var $m_Control;
    var $m_Index;
    
    function CuPage()
    {
        $this->m_Control = array();
        $this->m_Index = 0;
    }
    

    /************************************************
    * 函式名稱: LoadFile
    * 函式說明: 載入html檔
    ************************************************/   
    function LoadFile($filename)
    {
        $html = LoadFile("resource/Task.form.html");
        $this->ExplodeForm($html);
        $this->CombineControl();
    }


    /************************************************
    * 函式名稱: ExplodeForm
    * 函式說明: 將Html Form 轉為 控制項陣列
    ************************************************/       
    function ExplodeForm($html)
    {
        $html_array = explode("<", $html);
        
        foreach( $html_array as $key => $value )
        {
            if( ereg( "^input", $value ) )
            {
                list($webcode, $str) = explode(">", $value);
                
                $object_Attribute = explode(" ", $webcode);
                $this->CreateWebControl($object_Attribute);
                
                $this->CreateHTMLString( $str );
            }
            else if( $value != "" )
            {
                $this->CreateHTMLString( "<" . $value );
            }
        }       
    }
    

    /************************************************
    * 函式名稱: CombineControl
    * 函式說明: 叫用這個函式, 來派發form 物件到類別內
    ************************************************/
    function CombineControl()
    {
        foreach( $this->m_Control as $key => $value )
        {
            if( $value->Attribute["name"] == "" )
                continue;
            
            $name = $value->Attribute["name"];
            $this->$name = &$this->m_Control[$key];
        }
        
    }
    
    
    /************************************************
    * 函式名稱: OnProcess
    * 函式說明: 子類別繼承這個函式後對表單的操作函式
    ************************************************/
    function OnProcess()
    {
            
    }
    
    
    /************************************************
    * 函式名稱: AddObject
    * 函式說明: 將CuWebControl加入CuPage陣列
    ************************************************/   
    function AddObject($object)
    {
        $this->m_Index = $this->m_Index + 1;
        $this->m_Control[$this->m_Index] = $object;       
    }
    
    
    /************************************************
    * 函式名稱: SetObject
    * 函式說明: 將CuWebControl加入CuPage陣列, 這裡會掃name參數, 找到一樣的就蓋掉, 找不到就轉叫 AddObject
    ************************************************/
    function SetObject($object)
    {
        
        $index = $this->GetObjectIndex($object->Get("name"));
        if( $index == 0 )
            $this->AddObject($object);
        else
            $this->m_Control[$index] = $object;

    }
    
    
    /************************************************
    * 函式名稱: GetObjectIndex
    * 函式說明: 依名稱尋找索引值
    ************************************************/
    function GetObjectIndex($name)
    {
        foreach( $this->m_Control as $key => $value )
        {
            if( $name == $value->Attribute["name"] )
                return $key;
        }
    }
    
    
    /************************************************
    * 函式名稱: GetObject
    * 函式說明: 依名稱尋找元件 -- 這裡傳回的是copy版, 
    ************************************************/   
    function GetObject($name)
    {
        
        foreach( $this->m_Control as $key => $value )
        {
            if( $name == $value->Attribute["name"] )
                return $this->m_Control[$key];
        }

    }   


    /************************************************
    * 函式名稱: CreateWebControl
    * 函式說明: 將處理好一半的HTML碼轉為CuWebControl, 並且叫用SetObject
    ************************************************/       
    function CreateWebControl($html_tag_array)
    {
        
        $Control = new CuWebControl;
        foreach($html_tag_array as $Attribute_key => $Attribute_value)
        {
            list($key, $value) = explode("=", $Attribute_value);
            $value = split("\"", $value);
            $Control->Set($key, $value[1]);
        }
        
        $this->AddObject($Control);
        
    }


    /************************************************
    * 函式名稱: CreateHTMLString
    * 函式說明: 建構HTML字串元件除了可以轉換的 FORM INPUT 外, 其他的文字直接建文字元件
    ************************************************/           
    function CreateHTMLString($string)
    {
        if( $string == "" )
            return;
        
        $Control = new CuHTMLString();
        $Control->OnAdd( $string );
        $this->AddObject($Control);
        
    }
    
    
    function OnHTML()
    {
        $html = "";
        foreach( $this->m_Control as $key => $value )
        {
            if( $value != null )
                $html .= $value->OnHTML();
        }
        return $html;
    }
    
}

Form 的載入一般都直接使用HTML並且替換字串, 在這裡將form.html當做外部介面設定檔,
將 input 生成為可控制類別, 使用類別操控的方式來處理表單, 可以很方便的操作內容元件,
上面拿 tag input 來做範例.

2010年2月14日 星期日

CuTaskDlg

//

//***************************************
// 類別名稱:CuTask
// 功  能:工作記錄 對資料表 task 資料維護
//***************************************/
class CuTaskDlg  {

    // 成員變數
    // private
    var $created;
    
    // public
    var $title;
    var $description;
    var $account_id;


    // 資料庫關聯
    var $ado;
    var $record;
    
    // 靜態變數
    var $table_name = "hrc_task";
    
    /************************************************
    * 函式名稱: CuTaskDlg
    * 函式說明: 使用CuRecord作業
    ************************************************/       
    function CuTaskDlg($ado) {

        $this->ado = $ado;
        $this->record = new CuRecord($ado, $this->table_name, "sn");

    }
    
    
    /************************************************
    * 函式名稱: Save
    * 函式說明: 儲存 這個 啞資料類別不處理
    ************************************************/   
    function Save()
    {
        if(!($this->title))
            return;
            
        
        $this->created = date("Y-m-d H:i:s", time());
        $record = &$this->record;
        
        // 檢查是否有留言過
        $sn = $record->Load("title", "$this->title");
        if( $sn != "" )
            return;
        
        $record->SetField("created", $this->created );
        $record->SetField("title", $this->title);
        $record->SetField("description", $this->description);
        
        
        $record->SetField("account_id", $this->account_id);
        $record->Save(); 
    }
    
    
    /************************************************
    * 函式名稱: Load
    * 函式說明: 指定SN值 載入指定的資料項
    ************************************************/       
    function Load($sn)
    {
        $record = &$this->record;
        $record->Load("sn", $sn);
        
        $this->created  = $record->GetField("created");
        $this->title = $record->GetField("title");
        $this->description = $record->GetField("description");
        $this->account_id = $record->GetField("account_id");
        
    }
    
}



/*

-- 
-- 資料表格式: `hrc_task`
-- 

CREATE TABLE `hrc_task` (
  `sn` int(11) NOT NULL auto_increment,
  `created` timestamp NOT NULL default '0000-00-00 00:00:00',
  `title` varchar(256) NOT NULL,
  `description` text,
  `account_id` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY  (`sn`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

 created 記錄建立日期
 title 項目主旨
 description 詳細內容
 account_id 帳號索引 用來關聯是那位使用者寫入的 預設為0 
*/


2010年2月13日 星期六

CuCount



// CuCount.php

class CuCount
{
    var $ado;
    var $count_name;
    var $record;
    
    function CuCount(/*CuAdo*/ $ado, $count_name)
    {

        $this->ado = &$ado;
        $this->count_name = $count_name;
        $this->record = new CuRecord(&$ado, "hrc_count", "id");
        $this->record->Load("name", $this->count_name);

    }
    
    function Inc()
    {
        
        $record = &$this->record;
        
        $count = $record->GetField("count");
        $count = $count + 1;
        $record->SetField("count", $count);
        $record->SetField("name", $this->count_name);
        $record->Save();
        
        $this->AddLog();
        $CountLog = $this->CountLog();
        

        $TotalCount = $record->GetField("totalcount");
        $TotalCount = $TotalCount + $CountLog;

        return $TotalCount;
        
    }
    
    function CountLog( $date = "" )
    {
        $id = $this->record->GetField('id');
        if( $date != "" )
            $created_stmt = " AND created = '$date' ";
            
            
        $stmt = "SELECT * FROM hrc_countlog WHERE `count_id` = '". $id ."'" . $created_stmt;
        $this->ado->sql($stmt);   
        $result_table = $this->ado->fetch_array();
        return count($result_table);
        
    }
    
    function AddLog()
    {
                
        $CountLog = new CuRecord(&$this->ado, "hrc_countlog", "id");
        $created = date("Y-m-d", time());       
        $CountLog->SetField("created", $created);
        $CountLog->SetField("count_id", $this->record->GetField("id"));
        $CountLog->SetField("user_agent",  $GLOBALS["HTTP_USER_AGENT"]);
        $CountLog->Save();
        
    }
    
}

/*
CREATE TABLE `hrc_count` (
`id` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`name` VARCHAR( 64 ) NOT NULL ,
`count` INT( 11 ) NOT NULL ,
`totalcount` INT( 11 ) NOT NULL default '0',
INDEX ( `name` ) 
) ENGINE = MYISAM ;

CREATE TABLE `hrc_countlog` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`count_id` INT NOT NULL ,
`created` DATE NOT NULL default '0000-00-00',
`user_agent` varchar(256) NOT NULL,
INDEX ( `count_id` ) 
) ENGINE = MYISAM ;

*/


有了CuRecord & CuADO 後. 在處理資料表時就簡明多了

2010年2月12日 星期五

TuPokerRule - 分析牌型

// u_TPokerRule.pas

unit u_TPokerRule;

interface
uses
        Windows, Classes, SysUtils,
        StdCtrls,
        ch_LogMessages,

        u_TList,
        u_TDeck,
        u_TexasHoldConst;

type

//******************************************************************************
// 類別名稱:TuPokerRule
// 功  能:分析牌型
//******************************************************************************
        TuPokerRule = class
          private
            m_PokerRuleMessToFiles : TLogMessToFiles;
            m_nPokerRule : integer; // 牌型

            // 計算每個花色的牌有幾張
            m_aCategory : array[0..3] of integer;
            // 記錄 每種 數字 有幾張
            m_aSumIndex: array[0..CARD_INDEX_LIMIT] of integer;
            // 記錄有幾種牌型
            m_aSumRules: array[0..POKER_RULES_LIMIT - 1]of integer;

            // 暫存要分析的撲克
            m_TempPokerList : TuList; // type TCardData.nListIndex;
            m_CardDataList: TuList; // type TCardData;
            m_MaxRulePoker : TuList; // type TCardData; 最大的五張牌


            m_pDeck : TuDeck;

            function _GetFlushIndex(): Integer; // 抓同花是那一個花色

            function _GetMaxRules : Integer; // 取最大的牌型
            procedure _OnRanderMaxPoker( nRuleType:Integer ); // 依牌型抓最大的五張

            procedure _OnMaxPokerZilch;         // 抓 最大的五張
            procedure _OnMaxPokerOnePair;       // 抓 一對 最大的五張
            procedure _OnMaxPokerTwoPair;       // 抓 兩對 最大的五張
            procedure _OnMaxPokerThreeKind;     // 抓 三條 最大的五張
            procedure _OnMaxPokerStraight;      // 抓 順子 最大的五張
            procedure _OnMaxPokerFlush;         // 抓 同花 最大的五張
            procedure _OnMaxPokerFullHouse;     // 抓 葫蘆 最大的五張
            procedure _OnMaxPokerFourKind;      // 抓 鐵支 最大的五張
            procedure _OnMaxPokerStraightFlush; // 抓 同花順 最大的五張

            function _PokerRulesTwoPair:Integer;         // 檢查有沒有 兩對
            function _PokerRulesStraight : Integer;      // 檢查有沒有 順子
            function _PokerRulesFlush :Integer;          // 檢查有沒有 同花
            function _PokerRulesFullHouse: Integer;      // 檢查有沒有 葫蘆
            function _PokerRulesStraightFlush():Integer; // 檢查有沒有 同花順
            function _PokerRulesRoyalFlush():Integer;    // 檢查有沒有 同花順

            procedure _debug_LogPoker;// 將 牌 匯出
          public
            constructor Create(var pDeck: TuDeck);
            destructor Destroy(); override;

            procedure Init();
            procedure OnAddCard(nIndex:Integer);        // 將牌加入
            function GetPokerRule(): Integer;           // 取出最大的牌型
            procedure GetMaxRulePoker(var MaxPoker:TuList); // 將最大的五張牌寫入 MaxPoker

        end;



//******************************************************************************
// 類別名稱:TuUITextPokerRule
// 功  能:牌型顯示 文字版本
//******************************************************************************
        TuTextPokerRule = class
          private
            //m_uiText : TuUIText;
            m_strPokerRule : string; // 轉換完成的字串
            m_AToKTextList : TStringList; // A 到 K 的文字 字串
            m_PokerRulesFormat : TStringList; //
          public
            constructor Create();
            destructor Destroy(); override;
            procedure OnProcess(PokerRules: Word; var CardDataList : TuList ); // 牌型 五張牌
            property Text: string read m_strPokerRule;
        end;



implementation

// { TuUITextPokerRule }

constructor TuTextPokerRule.Create;
begin
        m_AToKTextList := TStringList.Create();
        if( Assigned( m_AToKTextList ) = True ) then begin
            m_AToKTextList.LoadFromFile( INI_DATA_PATH + 'AToKText_en.ini' );
        end;

        m_PokerRulesFormat := TStringList.Create();
        if( Assigned( m_PokerRulesFormat ) = True ) then begin
            m_PokerRulesFormat.LoadFromFile( INI_DATA_PATH + 'PokerRulesTextFormat_en.ini' );
        end;

end;


destructor TuTextPokerRule.Destroy;
begin
        m_PokerRulesFormat.Free;
        m_AToKTextList.Free;
  inherited;
end;


procedure TuTextPokerRule.OnProcess(PokerRules: Word;
  var CardDataList: TuList);
var
        strP1:string;
        strP2:string;

        TmpCardData : TCardData;
        TmpCardDataList : TuList;
        nIndex : Integer;
begin

        if CardDataList.Count = 0 then
            exit;

        strP1 := '';
        strP2 := '';
        // 牌型
        case PokerRules of
          POKER_RULES_ZILCH: begin

              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP1 := m_AToKTextList.Strings[ nIndex ];
          end;
          POKER_RULES_ONE_PAIR: begin
              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP1 := Format('%ss',[m_AToKTextList.Strings[ nIndex ]]);

          end;

          POKER_RULES_TWO_PAIRS: begin
              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP1 := Format('%ss',[m_AToKTextList.Strings[ nIndex ]]);

              TmpCardData := CardDataList.GetItems(3);
              nIndex := TmpCardData.Index - 1;
              strP2 := Format('%ss',[m_AToKTextList.Strings[ nIndex ]]);
          end;

          POKER_RULES_THREE_KIND: begin
              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP1 := Format('%ss',[m_AToKTextList.Strings[ nIndex ]]);
          end;

          POKER_RULES_STRAIGHT: begin
              TmpCardData := CardDataList.GetItems(4);
              nIndex := TmpCardData.Index - 1;
              strP1 := m_AToKTextList.Strings[ nIndex ];

              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP2 := m_AToKTextList.Strings[ nIndex ];
          end;

          POKER_RULES_FLUSH: begin
              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP1 := m_AToKTextList.Strings[ nIndex ];

          end;

          POKER_RULES_FULLHOUSE: begin
              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP1 := Format('%ss',[m_AToKTextList.Strings[ nIndex ]]);

              TmpCardData := CardDataList.GetItems(3);
              nIndex := TmpCardData.Index - 1;
              strP2 := Format('%ss',[m_AToKTextList.Strings[ nIndex ]]);
          end;

          POKER_RULES_FOUR_KIND: begin
              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP1 := Format('%ss',[m_AToKTextList.Strings[ nIndex ]]);
          end;

          POKER_RULES_STRAIGHT_FLUSH: begin
              TmpCardData := CardDataList.GetItems(4);
              nIndex := TmpCardData.Index - 1;
              strP1 := m_AToKTextList.Strings[ nIndex ];

              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP2 := m_AToKTextList.Strings[ nIndex ];
          end;

//          POKER_RULES_STRAIGHT_FLUSH: begin
//              TmpCardData := CardDataList.GetItems(0);
//              nIndex := TmpCardData.Index - 1;
//              strP1 := m_AToKTextList.Strings[ nIndex ];
//
//              TmpCardData := CardDataList.GetItems(4);
//              nIndex := TmpCardData.Index - 1;
//              strP2 := m_AToKTextList.Strings[ nIndex ];
//          end;


        end;

        m_strPokerRule := Format(m_PokerRulesFormat.Strings[PokerRules], [strP1, strP2]);

end;

constructor TuPokerRule.Create(var pDeck: TuDeck);
begin
        m_pDeck := pDeck;
        m_TempPokerList := TuList.Create();
        m_MaxRulePoker := TuList.Create();
        m_CardDataList := TuList.Create();

        m_PokerRuleMessToFiles := TLogMessToFiles.Create('PokerRuleMessage.txt');
end;

destructor TuPokerRule.Destroy;
begin
        m_PokerRuleMessToFiles.Free;
        m_TempPokerList.Free;
        m_MaxRulePoker.Free;
        m_CardDataList.Free;
end;


//******************************************************************************
// 函式名稱:Init
// 功  能:使用TuPokerRule 之前要先呼叫Init 用來清除所有資料
//******************************************************************************
procedure TuPokerRule.Init;
var
        i:integer;
begin

        // 初始化 PokerRules 記錄
        m_nPokerRule := POKER_RULES_ZILCH;

        // 清除花色記錄器
        for i := 0 to High(m_aCategory) do begin
            m_aCategory[i] := 0;
        end;

        // 清除牌數字記錄器
        for i := 0 to High(m_aSumIndex) do begin
            m_aSumIndex[i] := 0;
        end;

        // 清除牌數字記錄器
        for i := 0 to High(m_aSumRules) do begin
            m_aSumRules[i] := 0;
        end;

        // 清除暫存陣列
        m_TempPokerList.Clear();
        m_MaxRulePoker.Clear();
        m_CardDataList.Clear();
end;


//******************************************************************************
// 函式名稱:OnAddCard
// 功  能:將要運牌的牌加入TuPokerRule
//******************************************************************************
procedure TuPokerRule.OnAddCard(nIndex:Integer);
begin

        if( nIndex = - 1 ) then begin
            exit;
        end;
        m_TempPokerList.Add(Pointer(nIndex));
        m_CardDataList.Add(m_pDeck.Items(nIndex));
end;


//******************************************************************************
// 函式名稱:GetPokerRule
// 功  能:TuPokerRule 最主要的函式 計算牌型 計算最大的五張牌
//******************************************************************************
function TuPokerRule.GetPokerRule():Integer ;
var

        i: integer;
        nNum: integer;
        nListIndex: integer;
        nCategory : integer;
        // 有幾對
        nPairCount : integer;
        nThreeCount : integer;


begin
    try
        if m_TempPokerList.Count = 0 then  // 沒有牌不用處理
          exit;

        m_CardDataList.Sort(compareByPoker);

        for i := 0 to m_TempPokerList.Count - 1 do begin

            nListIndex := Integer(m_TempPokerList.GetItems(i));
            nCategory := m_pDeck.Category(nListIndex);
            nNum :=  m_pDeck.Index(nListIndex);

            // 計數每種花色有幾張
            m_aCategory[nCategory] := m_aCategory[nCategory] + 1;

            // 計數 同樣數字的撲克牌有幾張
            m_aSumIndex[nNum] :=  m_aSumIndex[nNum] + 1;

            if nNum = 13 then
                m_aSumIndex[0] :=  m_aSumIndex[0] + 1;

        end;

        for i := 1 to High(m_aSumIndex) do begin
            case m_aSumIndex[i] of
                2: m_aSumRules[POKER_RULES_ONE_PAIR] :=  m_aSumRules[POKER_RULES_ONE_PAIR] + 1;     // 計數對子
                3: m_aSumRules[POKER_RULES_THREE_KIND] := m_aSumRules[POKER_RULES_THREE_KIND] + 1;  // 計數三條
                4: m_aSumRules[POKER_RULES_FOUR_KIND] := m_aSumRules[POKER_RULES_FOUR_KIND] + 1;   // 計數四隻
            end;
        end;

        // 這裡有牌型是互斥的 可以使用 if else 作區分加快計算
        m_aSumRules[POKER_RULES_TWO_PAIRS] := _PokerRulesTwoPair();  // 檢查 兩對
        m_aSumRules[POKER_RULES_STRAIGHT] := _PokerRulesStraight();  // 檢查 順子
        m_aSumRules[POKER_RULES_FLUSH] := _PokerRulesFlush();        // 檢查 同花
        m_aSumRules[POKER_RULES_FULLHOUSE] := _PokerRulesFullHouse(); // 檢查 葫蘆
        m_aSumRules[POKER_RULES_STRAIGHT_FLUSH] := _PokerRulesStraightFlush();// 檢查 同花順
        m_aSumRules[POKER_RULES_ROYAL_FLUSH] := _PokerRulesRoyalFlush();  // 檢查 大同花順

        Result := _GetMaxRules();
        _OnRanderMaxPoker(Result);

      except
          m_PokerRuleMessToFiles.m_WriteTXTOne('GetPokerRule', 1);
      end;


end;


//******************************************************************************
// 函式名稱:_OnRanderMaxPoker
// 功  能:依牌型種類 抓出最大的五張牌
//******************************************************************************
procedure TuPokerRule._OnRanderMaxPoker(nRuleType: Integer);
begin

        case nRuleType of
            POKER_RULES_ZILCH:        _OnMaxPokerZilch;       // 沒有
            POKER_RULES_ONE_PAIR:     _OnMaxPokerOnePair;     // 一對
            POKER_RULES_TWO_PAIRS:    _OnMaxPokerTwoPair;     // 兩對
            POKER_RULES_THREE_KIND:   _OnMaxPokerThreeKind;   // 三條
//          POKER_RULES_SMALL_STRAIGHT:                     // 小順子
            POKER_RULES_STRAIGHT:     _OnMaxPokerStraight;    // 順子
            POKER_RULES_FLUSH:        _OnMaxPokerFlush;           // 同花
            POKER_RULES_FULLHOUSE:    _OnMaxPokerFullHouse;   // 葫蘆
            POKER_RULES_FOUR_KIND:    _OnMaxPokerFourKind;    // 鐵支
            POKER_RULES_STRAIGHT_FLUSH:_OnMaxPokerStraightFlush;  // 同花順
            POKER_RULES_ROYAL_FLUSH:  _OnMaxPokerStraightFlush;   // 大同花順
        end;

end;


//******************************************************************************
// 函式名稱:_GetMaxRules
// 功  能:選出 最大的牌型
//******************************************************************************
function TuPokerRule._GetMaxRules() : Integer;
var
        i : Integer;
begin

        for i := POKER_RULES_LIMIT - 1  downto POKER_RULES_ZILCH do begin
            if( m_aSumRules[i] > 0 ) then begin
                m_nPokerRule := i;
                break;
            end;
        end;
        Result := m_nPokerRule;

end;


//******************************************************************************
// 函式名稱:PokerRulesTwoPair
// 功  能:檢查有沒有兩對
//******************************************************************************
function TuPokerRule._PokerRulesTwoPair():integer;
begin

        if  m_aSumRules[POKER_RULES_ONE_PAIR] < 2 then
        begin
            Result := 0;
            exit;
        end;
        Result := 1;

end;


//******************************************************************************
// 函式名稱:PokerRulesStraight
// 功  能:檢查牌型 順子 & 順便檢查是不是最小順
//******************************************************************************
function TuPokerRule._PokerRulesStraight : integer;
var
        i : integer;
        nCountStraight : integer;
        nMaxCountStraight : integer;
begin
        nCountStraight := 0;
        nMaxCountStraight := 0;

        Result := 0;

        for i := High(m_aSumIndex) downto 0  do begin
            if m_aSumIndex[i] = 0 then
                nCountStraight := 0;

            if m_aSumIndex[i] > 0 then
                nCountStraight := nCountStraight + 1;

            if nMaxCountStraight < nCountStraight then
                nMaxCountStraight := nCountStraight;
        end;

        // 有超過5張連續的牌 代表有順子
        if nMaxCountStraight >= 5 then begin
            Result := 1;
        end;

        // 這裡要另外檢查 是否為最小順  A 2 3 4 5

        if( m_aSumIndex[1] > 0) And
          ( m_aSumIndex[2] > 0) And
          ( m_aSumIndex[3] > 0) And
          ( m_aSumIndex[4] > 0) And
          ( m_aSumIndex[0] > 0) then begin

            if nMaxCountStraight = 5 then begin
                m_aSumRules[POKER_RULES_SMALL_STRAIGHT] := 1;
            end;
            
            Result := 1;
        end;


end;


//******************************************************************************
// 函式名稱:PokerRulesFlush
// 功  能:檢查牌型 同花
//******************************************************************************
function TuPokerRule._PokerRulesFlush :integer;
var
        i : integer;
        nListIndex : integer;
        nNum : integer;
        nCategory : integer;
begin
        Result := 0;
        // 檢查是否有五張的花色
        for i := 0 to High(m_aCategory) do begin
            if( m_aCategory[i] >= 5 ) then begin
                m_nPokerRule := POKER_RULES_FLUSH;
                Result := 1;
            end;
        end;

end;


//******************************************************************************
// 函式名稱:PokerRulesFullHouse
// 功  能:檢查牌型 葫蘆
//******************************************************************************
function TuPokerRule._PokerRulesFullHouse: integer;
begin

        Result := 0;
        case m_aSumRules[POKER_RULES_THREE_KIND] of
            // 有兩組三條
            2: Result := 1;
            // 有一組三條 + 一組對子
            1:
                begin
                if(m_aSumRules[POKER_RULES_ONE_PAIR] > 0 ) then
                    Result := 1;
                end;
        end;
    
end;


// 加入了 m_CardDataList 找時間改寫..
//******************************************************************************
// 函式名稱:PokerRulesStraightFlush
// 功  能:檢查牌型 同花順
//******************************************************************************
function TuPokerRule._PokerRulesStraightFlush():Integer ;
var
        i : Integer;
        nA : Integer;
        nTemp : Integer;
        nCategoryIndex: Integer;
        nCategory2Index: Integer;
        nCategory3Index: Integer;

        nSum: Integer;
        nMaxSum : Integer;

        aArray : TuList;

        str : String;
        strFileName :string;

begin

        Result := 0;
        // 沒有同花 跟 順子 就不用檢查 同花順        
        if ( m_aSumRules[POKER_RULES_STRAIGHT] = 0 ) Or
           (m_aSumRules[POKER_RULES_FLUSH] = 0) then
           exit;


        aArray := TuList.Create();

        for i := 0 to m_TempPokerList.Count - 1  do begin
            aArray.Add(m_TempPokerList.GetItems(i));
        end;

        aArray.Sort(compareByInteger);

        nCategoryIndex := _GetFlushIndex();


        // 檢查有沒有連續的順子
        nSum := 0;
        nMaxSum := 0;
        for i := 0 to m_TempPokerList.Count - 2 do
        begin
            nCategory2Index :=  m_pDeck.Category(Integer(aArray.GetItems(i + 1)));
            nCategory3Index :=  m_pDeck.Category(Integer(aArray.GetItems(i)));

            if( Integer(aArray.GetItems(i + 1)) - Integer(aArray.GetItems( i )) = 1 ) And
            ( nCategory2Index = nCategory3Index ) then
            begin
                nSum := nSum + 1;
                if( nMaxSum < nSum ) then
                    nMaxSum := nMaxSum + 1;
            end
            else
            begin
                nSum := 0;
            end;
        end;

        if( nMaxSum >= 4 ) then
        begin
            Result := 1;
            aArray.Free();
            exit;
        end;

        // 如果有小順 要另外檢查  只要檢查 有沒有同花色A 就行了
        if( nMaxSum <> 3 ) Or
          (m_aSumRules[POKER_RULES_SMALL_STRAIGHT] = 0 )then begin
            aArray.Free();
            exit;
        end;

        // 計算同花色的A 的索引值
        nA := nCategoryIndex * 13 + 12 ;
        for i := 0 to m_TempPokerList.Count -1 do
        begin
            //nTemp := aArray[i];
            if Integer(aArray.GetItems(i)) = nA then
            begin
                Result := 1;
                break;
            end;
        end;

        aArray.Free();


end;


//******************************************************************************
// 函式名稱:_PokerRulesRoyalFlush
// 功  能:檢查牌型 大同花順
//******************************************************************************
function TuPokerRule._PokerRulesRoyalFlush: Integer;
var
        i:Integer;
        j:integer;
        TmpCardData : TCardData;
        nCategory:integer;
        nCardIndex:integer;
begin
        Result := 0;
        // 沒有同花順 就不用檢查 大同花順
        if ( m_aSumRules[POKER_RULES_STRAIGHT_FLUSH] = 0 ) then
           exit;

        nCategory := _GetFlushIndex();
        nCardIndex := 13;

        // 抓滿五張
        j := m_CardDataList.Count - 1;
        for i := 0 to 4 do begin
            TmpCardData := m_CardDataList.GetItems(j);
            if (TmpCardData.Index <> nCardIndex) Or
               (TmpCardData.Category <> nCategory) then begin 
               Result := 0;
               exit;

            end;
            j := j - 1;
            nCardIndex := nCardIndex - 1;
        end;

        Result := 1;

end;


//******************************************************************************
// 函式名稱:GetMaxRulePoker
// 功  能:計算最大的牌型
//******************************************************************************
procedure TuPokerRule.GetMaxRulePoker(var MaxPoker: TuList);
var
        i : integer;
begin

        MaxPoker.Clear();
        for i := 0 to m_MaxRulePoker.Count -1 do begin
            MaxPoker.Add(m_MaxRulePoker.GetItems(i));
        end;
        
end;


//******************************************************************************
// 函式名稱:_OnMaxPokerOnePair
// 功  能:將沒有任何牌形 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerZilch;
var
        i: integer;
        j: integer;
        TmpCardData : TCardData;
begin
        // 抓五張
        for j := m_CardDataList.Count - 1 downto 0 do begin
            TmpCardData := m_CardDataList.GetItems(j);
            m_MaxRulePoker.Add(TmpCardData);
            if m_MaxRulePoker.Count = 5 then begin
                Break;
            end;
        end;
end;


//******************************************************************************
// 函式名稱:_OnMaxPokerOnePair
// 功  能:將牌形一對 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerOnePair;
var
        i: integer;
        j: integer;
        nNum: integer;

        TmpCardData : TCardData;
begin
        // 抓最大的一對牌
        for i := High(m_aSumIndex) downto 1 do begin
            if m_aSumIndex[i] = 2 then begin
                for j := 0 to m_CardDataList.Count - 1 do begin
                    TmpCardData := m_CardDataList.GetItems(j);
                    //nListIndex := TmpCardData.ListIndex;
                    nNum :=  TmpCardData.Index;
                    if nNum = i then begin
                        m_MaxRulePoker.Add(TmpCardData);
                    end;
                end;
                Break;
            end;
        end;

        // 抓剩下的三張
        for j := m_CardDataList.Count - 1 downto 0 do begin
            TmpCardData := m_CardDataList.GetItems(j);
            if m_aSumIndex[TmpCardData.Index] = 2 then begin
                Continue;
            end;

            m_MaxRulePoker.Add(TmpCardData);
            if m_MaxRulePoker.Count = 5 then begin
                Break;
            end;
        end;

end;


//******************************************************************************
// 函式名稱:_OnMaxPokerTwoPair
// 功  能:將牌形兩對 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerTwoPair;
var

        i: integer;
        j: integer;
        nNum: integer;
        nListIndex: integer;
        nPairCount: integer;
        TmpCardData : TCardData;
begin

        // 抓最大的兩對牌
        nPairCount := 0;
        for i := High(m_aSumIndex) downto 1 do begin
            if m_aSumIndex[i] = 2 then begin
                nPairCount := nPairCount + 1;
                for j := 0 to m_CardDataList.Count - 1 do begin
                    TmpCardData := m_CardDataList.GetItems(j);
                    //nListIndex := TmpCardData.ListIndex;
                    nNum :=  TmpCardData.Index;
                    if nNum = i then begin
                        m_MaxRulePoker.Add(TmpCardData);
                    end;
                end;
                if nPairCount = 2 then begin
                    break;
                end;
            end;
        end;

        // 抓第五張
        nPairCount := 0;
        for j := m_CardDataList.Count - 1 downto 0 do begin
            TmpCardData := m_CardDataList.GetItems(j);

            if m_aSumIndex[TmpCardData.Index] = 2 then begin
                nPairCount := nPairCount + 1;
                if nPairCount <= 4 then begin
                    Continue;
                end;
            end;

            m_MaxRulePoker.Add(TmpCardData);
            break;

        end;
end;


//******************************************************************************
// 函式名稱:_OnMaxPokerThreeKind
// 功  能:將牌形三條 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerThreeKind;
var
        i: integer;
        j: integer;
        nNum: integer;

        TmpCardData : TCardData;
begin
        // 抓三條
        for i := High(m_aSumIndex) downto 1 do begin
            if m_aSumIndex[i] = 3 then begin
                for j := 0 to m_CardDataList.Count - 1 do begin
                    TmpCardData := m_CardDataList.GetItems(j);
                    //nListIndex := TmpCardData.ListIndex;
                    nNum :=  TmpCardData.Index;
                    if nNum = i then begin
                        m_MaxRulePoker.Add(TmpCardData);
                    end;
                end;
                Break;
            end;
        end;

        // 抓滿五張
        for j := m_CardDataList.Count - 1 downto 0 do begin
            TmpCardData := m_CardDataList.GetItems(j);
            if m_aSumIndex[TmpCardData.Index] = 3 then begin
                Continue;
            end;

            m_MaxRulePoker.Add(TmpCardData);
            if m_MaxRulePoker.Count = 5 then begin
                Break;
            end;
        end;


end;


//******************************************************************************
// 函式名稱:_OnMaxPokerStraight
// 功  能:將牌形 順子 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerStraight;
var
        i : integer;

        nCardDataIndex : integer;
        nCardDataNextIndex : Integer;
        nCountStraight : integer;
        nMaxCountStraight : integer;

        TmpCardData : TCardData;
        TmpCardDataNext : TCardData;
begin

        _debug_LogPoker();
        
        nCountStraight := 0;
        nMaxCountStraight := 0;

        nCardDataIndex := m_CardDataList.Count - 1;
        nCardDataNextIndex := nCardDataIndex - 1;
        for i := m_CardDataList.Count - 1 downto 1 do begin
            TmpCardData := m_CardDataList.GetItems(nCardDataIndex);
            TmpCardDataNext := m_CardDataList.GetItems(nCardDataNextIndex);

            // 先加入第一張牌
            if m_MaxRulePoker.Count = 0 then
                m_MaxRulePoker.Add(TmpCardData);

            // 如果 兩張牌面數字一樣 換下一張
            while (nCardDataNextIndex > 0) And
                (TmpCardData.Index = (TmpCardDataNext.Index )) do begin
                nCardDataNextIndex := nCardDataNextIndex - 1;
                TmpCardDataNext := m_CardDataList.GetItems(nCardDataNextIndex);
            end;

            // 下一張是不是比前一張少一
            if TmpCardData.Index = (TmpCardDataNext.Index + 1) then begin
                m_MaxRulePoker.Add(TmpCardDataNext);
            end else begin
                m_MaxRulePoker.Clear;
            end;

            // 超過五張
            if m_MaxRulePoker.Count = 5 then
                Break;

            nCardDataIndex := nCardDataNextIndex;
            nCardDataNextIndex := nCardDataNextIndex - 1;

            if nCardDataIndex = 0 then begin
                Break;
            end;

        end;

        // 如果是小順 要另外處理A
        if m_aSumRules[POKER_RULES_SMALL_STRAIGHT] <> 0 then begin
            for i := m_CardDataList.Count - 1 downto 0 do begin
                TmpCardData := m_CardDataList.GetItems(i);
                if TmpCardData.Index = 13 then begin
                    m_MaxRulePoker.Add(TmpCardData);
                    break;
                end;
            end;
        end;


end;


//******************************************************************************
// 函式名稱:_OnMaxPokerFlush
// 功  能:將牌形 同花 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerFlush;
var
        i : integer;
        nListIndex : integer;
        nNum : integer;
        nCategory : integer;

        TmpCardData : TCardData;
begin

        nCategory := _GetFlushIndex();

        for i := m_CardDataList.Count - 1 downto 0 do begin
            TmpCardData := m_CardDataList.GetItems(i);
            if TmpCardData.Category = nCategory then begin
                m_MaxRulePoker.Add(TmpCardData);
            end;

            if m_MaxRulePoker.Count = 5 then
                Break;
        end;
end;


//******************************************************************************
// 函式名稱:_OnMaxPokerFullHouse
// 功  能:將牌形 葫蘆 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerFullHouse;
var
        i: integer;
        j: integer;
        nMaxThreeKind : integer;
        TmpCardData : TCardData;
begin
        // 抓最大的三條
        for i := High(m_aSumIndex) downto 1 do begin
            if m_aSumIndex[i] = 3 then begin

                for j := m_CardDataList.Count - 1 downto 0 do begin
                    TmpCardData := m_CardDataList.GetItems(j);
                    if TmpCardData.Index = i then begin
                        m_MaxRulePoker.Add(TmpCardData);
                    end;

                    if m_MaxRulePoker.Count = 3 then
                        Break;
                end;
                nMaxThreeKind := i;
                Break;
            end;
        end;

        // 抓最大的對子
        for i := High(m_aSumIndex) downto 1 do begin
            if m_aSumIndex[i] >= 2 then begin
                if i = nMaxThreeKind then begin
                    continue;
                end;

                for j := m_CardDataList.Count - 1 downto 0 do begin
                    TmpCardData := m_CardDataList.GetItems(j);
                    if TmpCardData.Index = i then begin
                        m_MaxRulePoker.Add(TmpCardData);
                    end;

                    if m_MaxRulePoker.Count = 5 then begin
                        Exit;
                    end;
                end;
            end;
        end;

end;


//******************************************************************************
// 函式名稱:_OnMaxPokerFourKind
// 功  能:將牌形 鐵支 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerFourKind;
var
        i: integer;
        j: integer;
        nMaxFourKind : integer;
        TmpCardData : TCardData;
begin
        // 抓最大的鐵支四張
        for i := High(m_aSumIndex) downto 1 do begin
            if m_aSumIndex[i] = 4 then begin

                for j := m_CardDataList.Count - 1 downto 0 do begin
                    TmpCardData := m_CardDataList.GetItems(j);
                    if TmpCardData.Index = i then begin
                        m_MaxRulePoker.Add(TmpCardData);
                    end;

                    if m_MaxRulePoker.Count = 4 then
                        Break;
                end;
                nMaxFourKind := i;
                Break;
            end;
        end;

        // 抓滿五張
        for j := m_CardDataList.Count - 1 downto 0 do begin
            TmpCardData := m_CardDataList.GetItems(j);
            if TmpCardData.Index = nMaxFourKind then begin
                Continue;
            end;

            m_MaxRulePoker.Add(TmpCardData);
            if m_MaxRulePoker.Count = 5 then begin
                Break;
            end;
        end;

end;


//******************************************************************************
// 函式名稱:_OnMaxPokerStraightFlush
// 功  能:將牌形 同花順 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerStraightFlush;
var
        i : integer;

        nCardDataIndex : integer;
        nCardDataNextIndex : Integer;
        nCountStraight : integer;
        nMaxCountStraight : integer;

        TmpCardData : TCardData;
        TmpCardDataNext : TCardData;

        nCategory : integer;
begin
        _debug_LogPoker();

        nCategory := _GetFlushIndex();

        
        nCountStraight := 0;
        nMaxCountStraight := 0;

        nCardDataIndex := m_CardDataList.Count - 1;
        for i := m_CardDataList.Count - 1 downto 1 do begin

            TmpCardData := m_CardDataList.GetItems(nCardDataIndex);
            while TmpCardData.Category <> nCategory do begin
                nCardDataIndex := nCardDataIndex - 1;
                TmpCardData := m_CardDataList.GetItems(nCardDataIndex);
            end;

            nCardDataNextIndex := nCardDataIndex - 1;
            TmpCardDataNext := m_CardDataList.GetItems(nCardDataNextIndex);
            while (nCardDataNextIndex > 0 ) And
                (TmpCardDataNext.Category <> nCategory) do begin
                nCardDataNextIndex := nCardDataNextIndex - 1;
                TmpCardDataNext := m_CardDataList.GetItems(nCardDataNextIndex);
            end;

            // 先加入第一張牌
            if m_MaxRulePoker.Count = 0 then
                m_MaxRulePoker.Add(TmpCardData);

//            同樣花色不可能數字一樣 // 如果 兩張牌面數字一樣 換下一張
//            while TmpCardData.Index = (TmpCardDataNext.Index ) do begin
//                nCardDataNextIndex := nCardDataNextIndex - 1;
//                TmpCardDataNext := m_CardDataList[nCardDataNextIndex];
//            end;

            // 下一張是不是比前一張少一
            if TmpCardData.Index = (TmpCardDataNext.Index + 1) then begin
                m_MaxRulePoker.Add(TmpCardDataNext);
            end else begin
                m_MaxRulePoker.Clear;
            end;

            // 超過五張
            if m_MaxRulePoker.Count = 5 then
                Break;

            nCardDataIndex := nCardDataNextIndex;
//            nCardDataNextIndex := nCardDataNextIndex - 1;

            if nCardDataIndex = 0 then begin
                Break;
            end;

        end;

        // 如果是小順 要另外處理A
        if m_aSumRules[POKER_RULES_SMALL_STRAIGHT] <> 0 then begin
            for i := m_CardDataList.Count - 1 downto 0 do begin
                TmpCardData := m_CardDataList.GetItems(i);
                if TmpCardData.Index = 13 then begin
                    m_MaxRulePoker.Add(TmpCardData);
                    break;
                end;
            end;
        end;

end;


//******************************************************************************
// 函式名稱:_GetFlushIndex
// 功  能:傳回同花的花色索引
//******************************************************************************
function TuPokerRule._GetFlushIndex: Integer;
var
        i:integer;
begin

        Result := -1 ;
        // 查一下什麼同花
        for i := 0 to High(m_aCategory) do
        begin
            if( m_aCategory[i] >= 5 ) then
            begin
                Result := i;
                break;
            end;
        end;

        if Result = -1 then begin
            Result := 0;
        end;

        
end;


procedure TuPokerRule._debug_LogPoker;
var
        i:Integer;
        str:String;
        strPoker:string;
        TmpCardData : TCardData;
begin
        exit;
        str := '';
        strPoker := '';
        for i := m_CardDataList.Count -1 downto 0 do begin
            TmpCardData := m_CardDataList.GetItems(i);
            str := Format('%d ', [TmpCardData.Index] );
            strPoker := strPoker + str;
        end;
        m_PokerRuleMessToFiles.m_WriteTXTOne(strPoker, 1);

end;


end.


應該感受的出來這一份代碼表現的緊張, 在時間壓力下寫出來的代碼實在是慘無人道丫!

在接下來的C++版時會大力的改善 Switch 實在是個使用多型的好地方!

2010年2月11日 星期四

CuCompositeImage


//

class CuCompositeImage
{

    vector<IuImageEx*> _itsImage;

public:
    int GetSize();
    virtual IuImageEx* Get(int i){ return i < _itsImage.size() ? _itsImage[i] : NULL; }

    void clear();


    void add(IuImageEx* pImage){ _itsImage.push_back(pImage); }
    void push_back(IuImageEx* pImage){ _itsImage.push_back(pImage); }

    CuCompositeImage();
    virtual ~CuCompositeImage();

};


//


CuCompositeImage::CuCompositeImage()
{

}

CuCompositeImage::~CuCompositeImage()
{
}



void CuCompositeImage::clear()
{

    IuImageEx *pImage;
    vector<IuImageEx*>::iterator _itor; 

    _itor = _itsImage.begin();

    while(  _itor != _itsImage.end() )
    {

        pImage = *(_itor++);
        if( pImage )
            pImage->Release();
    }

    _itsImage.clear();

}

int CuCompositeImage::GetSize()
{
    return _itsImage.size();
}



在TuComposite還沒獨立出來之前, 每個需要Composite的部份都需要像上面這樣另外寫一份,也就是為何後來直接將Composite轉為Template的主要原因.

2010年2月10日 星期三

CuFont



//


class CuFont  
{
    HDC m_hDC;
    HFONT m_hFont;

public:
    void Release();
    void SetFontSize(int iFontSize);
    CuFont(HDC hDC);
    virtual ~CuFont();


private:
    CuFont(){}

};


//


CuFont::CuFont(HDC hDC):
m_hFont(NULL)
{
    m_hDC = hDC;
}

CuFont::~CuFont()
{

    if( m_hDC )
        Release();
}

void CuFont::SetFontSize(int iFontSize)
{
    if( !m_hDC )
        return;

    HFONT hFontCreated = NULL;
    HFONT hFont = (HFONT) GetStockObject(SYSTEM_FONT);

    hFontCreated = CuFontManager::Instance()->GetFontHandle(hFont, iFontSize);

    m_hFont = (HFONT)::SelectObject(m_hDC, hFontCreated);

    DeleteObject(hFont);

}

void CuFont::Release()
{
    if( m_hDC && m_hFont )
    {
        HFONT hFontCreated = (HFONT)::SelectObject(m_hDC, m_hFont);
    }

    m_hDC = NULL;
}

2010年2月9日 星期二

CuTimeZone -

//


#define RV_TIMEZONES    TEXT("Time Zones")
#define RK_CLOCK        TEXT("Software\\Microsoft\\Clock")
#define RV_INDST        TEXT("HomeDST")                     // are we currently in DST
#define RV_AUTODST      TEXT("AutoDST")
#define RV_DSTUI        TEXT("ShowDSTUI") 
#define RV_TIMEZONES    TEXT("Time Zones")
#define RV_DISPLAY      TEXT("Display")
#define RV_TZI          TEXT("TZI")
#define RV_DLT          TEXT("Dlt")
#define RV_STD          TEXT("Std")

#define ZoneHasDaylightTime(tzi)    (tzi.DaylightDate.wMonth && tzi.DaylightBias)

struct TZREG {
    LONG    Bias;
    LONG    StandardBias;
    LONG    DaylightBias;
    SYSTEMTIME StandardDate;
    SYSTEMTIME DaylightDate;
};

class CuTimeZone
{
    TIME_ZONE_INFORMATION m_TimeZoneInformation;

    vector<wstring> m_vecTimeZoneList;
    wstring m_strCurrZone;
    int m_nCurrZone;

public:
    CuTimeZone();
    virtual ~CuTimeZone();

    void Init();
    vector<wstring> &GetTimeZoneList(void);

    wstring GetCurrZone(){ return m_strCurrZone; }
    int GetCurrZoneIndex(){ return m_nCurrZone; }

    void SetCurrZone(int nCurrZone);
    void SetCurrZone(wstring strCurrZone);


};


//

CuTimeZone::~CuTimeZone()
{

}


CuTimeZone::CuTimeZone()
{
    CReg   Reg1(HKEY_LOCAL_MACHINE, RV_TIMEZONES), Reg2;

    TCHAR  szTimeZone[64];
    TCHAR  szTimeZoneStd[64];
    
//  TIME_ZONE_INFORMATION tziCurrent;
    DWORD tzid = GetTimeZoneInformation(&m_TimeZoneInformation);


    // Get DAYLIGHT States
    BOOL fInDST = (TIME_ZONE_ID_DAYLIGHT == tzid );

    CReg reg(HKEY_LOCAL_MACHINE, RK_CLOCK);
    reg.SetDW(RV_DSTUI, 1);

    
    while(Reg1.EnumKey(szTimeZone,64))
    {
        LPTSTR szTemp;
        Reg2.Reset();
        
        if(Reg2.Open(Reg1,szTimeZone))
        {
        
            // use the display name rather than the standard name 
            szTemp = (LPTSTR)Reg2.ValueSZ(RV_DISPLAY);

            Reg2.ValueSZ(RV_STD, szTimeZoneStd, sizeof(szTimeZoneStd));


            if(szTemp && 
                    ( !lstrcmp(szTimeZone, m_TimeZoneInformation.StandardName) ||
                      !lstrcmp(szTimeZoneStd, m_TimeZoneInformation.StandardName) )
                )
            {
                //lstrcpy(szZoneCurr,szTemp);
                m_nCurrZone = m_vecTimeZoneList.size();
                m_strCurrZone = szTemp;
            }

            m_vecTimeZoneList.push_back(szTemp);
        }

    }

}



vector<wstring> &CuTimeZone::GetTimeZoneList(void)
{
    return m_vecTimeZoneList;
}

void CuTimeZone::SetCurrZone(int nCurrZone)
{

    wstring strCurrZone = m_vecTimeZoneList[nCurrZone];
    SetCurrZone(strCurrZone);
}


void CuTimeZone::SetCurrZone(wstring strCurrZone)
{
    // Iterate over all timezones. Init new timezone to current just in case 
    TCHAR   szTimeZone[32];
    CReg    Reg1(HKEY_LOCAL_MACHINE, RV_TIMEZONES), Reg2;
    CReg reg(HKEY_LOCAL_MACHINE, RK_CLOCK);
    BOOL fUseDST =  ZoneHasDaylightTime(m_TimeZoneInformation);

    reg.SetDW(RV_AUTODST, fUseDST);
    while(Reg1.EnumKey(szTimeZone,32))
    {
        Reg2.Reset();
        if(Reg2.Open(Reg1,szTimeZone))
        {
            // if the display name matches the one in the combobox get the TZI data.
            if(!lstrcmp(strCurrZone.c_str(), Reg2.ValueSZ(RV_DISPLAY)))
            {
                TZREG  *pTZR = (TZREG*)Reg2.ValueBinary(RV_TZI);
                if(pTZR)
                {
                    m_TimeZoneInformation.Bias = pTZR->Bias;
                    m_TimeZoneInformation.StandardBias = pTZR->StandardBias;
                    m_TimeZoneInformation.DaylightBias = pTZR->DaylightBias;
                    m_TimeZoneInformation.StandardDate = pTZR->StandardDate;
                    m_TimeZoneInformation.DaylightDate = pTZR->DaylightDate;
                            
                    Reg2.ValueSZ(RV_DLT, m_TimeZoneInformation.DaylightName, 32);
                    lstrcpy(m_TimeZoneInformation.StandardName, szTimeZone);

                    m_strCurrZone = strCurrZone;
                    break;
                }
            }
        }
    }
    SetTimeZoneInformation(&m_TimeZoneInformation);


}
很特別的程式片段, 從APP裡移出來後就沒在理他, 等他被review 或需要改動功能時, 在來調整了

2010年2月8日 星期一

CuFontManager


// CuFontManager.h



class CuFontManager  
{
private:
    static  CuFontManager   m_pInstance; 
    map<int, HFONT>       m_mapFontHandle;

    CuFontManager();
public:
    virtual ~CuFontManager();

    static CuFontManager *Instance()
    {
        return &m_pInstance;
    }

    HFONT GetFontHandle(HFONT hFont,int iFontSize);
};


// CuFontManager.cpp



CuFontManager CuFontManager::m_pInstance;

CuFontManager::CuFontManager()
{

}

CuFontManager::~CuFontManager()
{
    map<int, HFONT>::iterator it;

    for(it = m_mapFontHandle.begin(); it != m_mapFontHandle.end(); it++) {
        HFONT hFontCreated = it->second;
        DeleteObject(hFontCreated);
    }

    m_mapFontHandle.clear();
}

HFONT CuFontManager::GetFontHandle(HFONT hFont,int iFontSize)
{
    HFONT hFontCreated;
    LOGFONT lf;
    map<int, HFONT>::const_iterator it;

    it = m_mapFontHandle.find(iFontSize);

    if(it == m_mapFontHandle.end()) {
        if (GetObject(hFont, sizeof LOGFONT, &lf)) {
            HDC hDC;

            hDC = ::GetDC(NULL);
            lf.lfHeight=-((iFontSize * GetDeviceCaps(hDC, LOGPIXELSY)) / 72);
            lf.lfWeight = FW_SEMIBOLD;

            hFontCreated = CreateFontIndirect(&lf);
            m_mapFontHandle.insert(map<int, HFONT>::value_type(iFontSize, hFontCreated));
            ReleaseDC(NULL, hDC);
        }
    }
    else
        hFontCreated = it->second;

    return hFontCreated;
}

2010年2月7日 星期日

CuLight

//


class CuLight  
{
    // CuLight 一實體後預存的值
    // 在解構時會將這個值寫回registey
    int m_nDefaultValue;

    LIGHT_INCVALUE  m_pfIncValue;
    LIGHT_DECVALUE  m_pfDecValue;
    LIGHT_GETVALUE  m_pfGetValue;
    LIGHT_SETVALUE  m_pfSetValue;

    LIGHT_GETMAXSTEP m_pfGetMaxStep;

    CuDllManager m_LightDll;


public:
    wstring strDllfile;
    

    CuLight();
    virtual ~CuLight(); 


    void Init();
    int OnGetValue(void);
    void OnSetValue(int n);

    void OnDecValue();
    void OnIncValue();
    void OnSave(){ m_nDefaultValue = OnGetValue(); }

    int OnGetMaxStep(){ return m_pfGetMaxStep(); }


};



//


CuLight::CuLight()
{

}

CuLight::~CuLight()
{
    OnSetValue(m_nDefaultValue);
}

void CuLight::Init()
{

    CuFile f;
    wstring strFile = f.GetModuleFileName(strDllfile.c_str());

    Verify(m_LightDll.LoadLibrary(strFile.c_str()) != NULL, L"can't Load Light_dll.dll Error");


    m_pfIncValue = (LIGHT_INCVALUE)m_LightDll.GetProcAddress(L"IncValue");
    Assert(m_pfIncValue != NULL, L"can't Load LIGHT_INCVALUE");

    m_pfDecValue = (LIGHT_DECVALUE)m_LightDll.GetProcAddress(L"DecValue");
    Assert(m_pfDecValue != NULL, L"can't Load LIGHT_DECVALUE");

    m_pfGetValue = (LIGHT_GETVALUE)m_LightDll.GetProcAddress(L"GetValue");
    Assert(m_pfGetValue != NULL, L"can't Load LIGHT_GETVALUE");

    m_pfSetValue = (LIGHT_SETVALUE)m_LightDll.GetProcAddress(L"SetValue");
    Assert(m_pfSetValue != NULL, L"can't Load LIGHT_SETVALUE");

    m_pfGetMaxStep = (LIGHT_GETMAXSTEP)m_LightDll.GetProcAddress(L"GetMaxStep");
    Assert(m_pfGetMaxStep != NULL, L"can't Load LIGHT_GETMAXSTEP");

    m_nDefaultValue = OnGetValue();

}

int CuLight::OnGetValue(void)
{ 
    int value;
    value = m_pfGetValue(); 
    return value;
}
void CuLight::OnSetValue(int n)
{ 
    m_pfSetValue(n); 
}

void CuLight::OnDecValue()
{
    m_pfDecValue(); 

    int value;
    value = m_pfGetValue(); 

}

void CuLight::OnIncValue()
{
    m_pfIncValue(); 
    int value;
    value = m_pfGetValue(); 

}
CE沒有標準, 所以定個介面元件對不同的機器實作獨一的DLL檔! 在設定檔裡指定要載入那一份DLL!

2010年2月6日 星期六

CuWinAppEx



// CuWinAppEx.h

class CuWinAppEx
{
private:
    static CuWinAppEx *m_pWinApp;

protected:

    class CuMainWnd : public CuWnd
    {
        virtual LRESULT OnMsg(MSG &msg)
        {
            return CuWinAppEx::GetTheApp()->OnMsg(msg);
        };
    };

    CuMainWnd m_MainWnd;

public:
    CuWinAppEx(void);
    virtual ~CuWinAppEx(void);


public:
    static CuWinAppEx* GetTheApp(); 
    virtual LRESULT OnMsg(MSG & msg);
    virtual BOOL Run();

public:
    int OnDestroy(void);
};


// CuWinAppEx.cpp



CuWinAppEx *CuWinAppEx::m_pWinApp;

CuWinAppEx::CuWinAppEx(void)
{
    m_pWinApp = this;
}

CuWinAppEx::~CuWinAppEx(void)
{
}

CuWinAppEx* CuWinAppEx::GetTheApp()
{
    return m_pWinApp;
}

LRESULT CuWinAppEx::OnMsg(MSG & msg)
{

    switch(msg.message)
    {
    case WM_DESTROY:
        OnDestroy();
        break;

    default:
        return FALSE;
    }

    return TRUE;
}

int CuWinAppEx::OnDestroy(void)
{
     ::PostQuitMessage(0);

     return 0;
}


BOOL CuWinAppEx::Run()
{
    MSG msg;

    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0)) 
    {
        //      if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return msg.wParam;
}

雖然函式裡有virtual 但有時後並不代表這個類別是打算被繼承的, 有一半是這個類別繼承了別人, 但在解構式定為virtual就表示, 這個類別100%是可以被繼承的, 或是一定要被繼承!

2010年2月5日 星期五

IuImageEx

class IuImageEx : public IuUnknown
{
public:
    virtual BOOL    Create( int nWidth, int nHeight, int nBPP = 16) = 0;

    virtual BYTE*   Data(void) = 0; 

    virtual UINT    Height() = 0;
    virtual void    Height(UINT nHeight) = 0;

    virtual UINT    Width() = 0;
    virtual void    Width(UINT nWidth) = 0;

    virtual UINT    BitCount() = 0;
    virtual void    BitCount(UINT nBitCount) = 0;

    virtual COLORREF GetPixel( int x, int y) = 0;
};
圖型編碼太多種, 但實際使用時, 也只有用到部份函式, 整個拉出介面時, 才發現用到的不多!

2010年2月4日 星期四

IuImageWnd

class IuImageWnd : public IuImageEx
{
public:
    virtual HDC GetDC() = 0;
    virtual void ReleaseDC() = 0;

    virtual BOOL BitBlt( HDC hDestDC, int xDest, int yDest, int nDestWidth, 
        int nDestHeight, int xSrc, int ySrc, DWORD dwROP = SRCCOPY ) = 0;

    virtual BOOL StretchBlt( HDC hDestDC, int xDest, int yDest, 
        int nDestWidth, int nDestHeight, int xSrc, int ySrc, int nSrcWidth, 
        int nSrcHeight, DWORD dwROP = SRCCOPY ) = 0;


    virtual operator HBITMAP() const = 0;

};
不管學院派對介面的定義為何! 在這裡介面獨立最好的地方是, 看起來就是輕巧, 使用起來壓力會小很多, 不必為了看到源碼或是太多功能搞的自己頭大!

2010年2月3日 星期三

CuImageEx

// CuImageEx.h



class CuImageEx : public IuImageEx 
{
    //圖高
    UINT    _nHeight;

    //圖寬
    UINT    _nWidth;

    // 圖的色素  :  16  
    UINT    _nBitCount;

    // 存放 圖形點陣列
    BYTE    *_bits;


public:
    CuImageEx();
    virtual ~CuImageEx();

    //////////////////////////////////////////////////////////////////
    // IuUnknown 公開虛擬界面 
    virtual ULONG Release();

    //////////////////////////////////////////////////////////////////
    // IuImage 公開虛擬界面 
    virtual BOOL Create(int nWidth, int nHeight, int nBPP = 16);

    virtual UINT    Height(){ return _nHeight; }
    virtual void    Height(UINT nHeight){ _nHeight = nHeight; }

    virtual UINT    Width(){ return _nWidth; }
    virtual void    Width(UINT nWidth){ _nWidth = nWidth; }

    virtual UINT    BitCount(){ return _nBitCount; }
    virtual void    BitCount(UINT nBitCount){ _nBitCount = nBitCount; }

    virtual COLORREF GetPixel( int x, int y);
    virtual BYTE*   Data(void){ return _bits; }


    //////////////////////////////////////////////////////////////////
    // 未公開虛擬界面 的 public 函式

    void Data(BYTE *pDate){ _bits = pDate; }

    void Destroy();

private:
    CuImageEx& operator =(CuImageEx& img);

};

 
// CuImageEx.cpp


CuImageEx::CuImageEx()
:_nHeight(0)
,_nWidth(0)
,_nBitCount(0)
,_bits(NULL)
{
}

CuImageEx::~CuImageEx()
{
    Destroy();
}

ULONG CuImageEx::Release()
{
    delete this;
    return 0;
}

BOOL CuImageEx::Create(int nWidth, int nHeight, int nBPP)
{

    Destroy();

    Height(nHeight);
    Width(nWidth);
    BitCount(nBPP);

    _bits = new BYTE[nWidth * nHeight * (nBPP >> 3)];

    return (_bits != NULL);

}

void CuImageEx::Destroy()
{

    Height(0);
    Width(0);
    BitCount(0);

    delete [] _bits;
    _bits = NULL;

}

COLORREF CuImageEx::GetPixel( int x, int y)
{

    WORD *pBits = (WORD*)this->Data();

    if( !pBits )
        return RGB(0, 0, 0);

    int nW = Width() ;

    // 
    if( nW % 2 )
        nW++;

    WORD wPixel = pBits[y * nW + x];

    return RGB( (wPixel >> 10 ) & 0x1f,
        (wPixel >> 5) & 0x1f,
        wPixel & 0x1f);
}

CuImageEx& CuImageEx::operator =(CuImageEx& img)
{
    
    if( this == &img )
        return *this;
    
    this->Create(img.Width() , img.Height(), img.BitCount() );

    memcpy(_bits, img._bits, _nWidth  * _nHeight * ( _nBitCount >> 3 ) );
        
    return *this;

}
與CuImageWnd 相異的地方在於, 若已經有一份點陣DC時, 其實其他的圖型運算是可以使用自製效能優化過的元件! 在這裡縮小圖結構方便替換運算元件!

2010年2月2日 星期二

CuImageWnd

// CuImageWnd.h



class CuImageWnd : public IuImageWnd
{

    // Image 的控制代碼
    HBITMAP m_hBitmap;

    // GetDC 時 暫存用的控制代碼
    HBITMAP m_hOldBitmap;

    // GetDC 時 暫存的DC控制代碼
    HDC m_hDC;

    // DC使用參考計數
    UINT m_nDCRefCount;

    CuImageEx m_ImageEx;
public:

    CuImageWnd();
    virtual ~CuImageWnd();

    //////////////////////////////////////////////////////////////////
    // IuUnknown 公開虛擬界面 
    virtual ULONG Release();

    //////////////////////////////////////////////////////////////////
    // IuImage 公開虛擬界面 
    virtual BOOL Create( int nWidth, int nHeight, int nBPP);

    virtual UINT    Height(){ return m_ImageEx.Height(); }
    virtual void    Height(UINT nHeight){ m_ImageEx.Height(nHeight); }

    virtual UINT    Width(){ return m_ImageEx.Width(); }
    virtual void    Width(UINT nWidth){ m_ImageEx.Width(nWidth); }

    virtual UINT    BitCount(){ return m_ImageEx.BitCount(); }
    virtual void    BitCount(UINT nBitCount){ m_ImageEx.BitCount(nBitCount); }

    virtual COLORREF GetPixel( int x, int y){ return m_ImageEx.GetPixel(x,y); }
    virtual BYTE*   Data(void){ return m_ImageEx.Data(); }

    //////////////////////////////////////////////////////////////////
    // IuImageWnd 公開虛擬界面 

        // window 支援函式


    virtual HDC GetDC();
    virtual void ReleaseDC();

    virtual BOOL BitBlt( HDC hDestDC, int xDest, int yDest, int nDestWidth, 
        int nDestHeight, int xSrc, int ySrc, DWORD dwROP = SRCCOPY );

    virtual BOOL StretchBlt( HDC hDestDC, int xDest, int yDest, 
        int nDestWidth, int nDestHeight, int xSrc, int ySrc, int nSrcWidth, 
        int nSrcHeight, DWORD dwROP = SRCCOPY );

    virtual operator HBITMAP() const;

    ///////////////////////////////////////////////////////////////////


    //////////////////////////////////////////////////////////////////
    // 未公開虛擬界面 的 public 函式
    void Destroy();

};



// CuImageWnd.cpp


CuImageWnd::CuImageWnd()
:m_hBitmap(NULL)
,m_hOldBitmap(NULL)
,m_hDC(NULL)
,m_nDCRefCount(0)
{
}


CuImageWnd::~CuImageWnd()
{

    Destroy();
}

ULONG CuImageWnd::Release()
{
    delete this;
    return 0;
}

BOOL CuImageWnd::Create( int nWidth, int nHeight, int nBPP)
{

    Destroy();

    BITMAPINFO  dibInfo;
    dibInfo.bmiHeader.biBitCount = nBPP;
    dibInfo.bmiHeader.biClrImportant = 0;
    dibInfo.bmiHeader.biClrUsed = 0;
    dibInfo.bmiHeader.biCompression = BI_RGB;
    dibInfo.bmiHeader.biHeight = nHeight;
    dibInfo.bmiHeader.biPlanes = 1;
    dibInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
    dibInfo.bmiHeader.biSizeImage = nWidth * nHeight * (nBPP >> 3 );
    dibInfo.bmiHeader.biWidth = nWidth;
    dibInfo.bmiHeader.biXPelsPerMeter = 0;
    dibInfo.bmiHeader.biYPelsPerMeter = 0;
    dibInfo.bmiColors[0].rgbBlue = 0;
    dibInfo.bmiColors[0].rgbGreen = 0;
    dibInfo.bmiColors[0].rgbRed = 0;
    dibInfo.bmiColors[0].rgbReserved = 0;

    Height(nHeight);
    Width(nWidth);
    BitCount(nBPP);

    void* ppvBits ;//= Data();

    m_hBitmap = ::CreateDIBSection(NULL, &dibInfo, DIB_RGB_COLORS,
        (void**)&ppvBits, NULL, 0);

    m_ImageEx.Data((BYTE*)ppvBits);
    
    return (BOOL)m_hBitmap;

}

void CuImageWnd::Destroy()
{
    if( m_hBitmap )
    {
        ::DeleteObject(m_hBitmap);
        m_hBitmap = NULL;
    }

    m_ImageEx.Data(0);

    Height(0);
    Width(0);
    BitCount(0);

}

HDC CuImageWnd::GetDC() 
{

    Assert(m_hBitmap != NULL, L" CuImage::GetDC() m_hBitmap != NULL");
    
    m_nDCRefCount++;
    if( m_hDC == NULL )
    {
        m_hDC = ::CreateCompatibleDC(NULL);
        m_hOldBitmap = HBITMAP(::SelectObject( m_hDC, m_hBitmap ));
    }

    return m_hDC;
}

void CuImageWnd::ReleaseDC() 
{
    HBITMAP hBitmap;

    Assert( m_hDC != NULL, L"");

    m_nDCRefCount--;
    if( m_nDCRefCount == 0 )
    {
        hBitmap = HBITMAP( ::SelectObject( m_hDC, m_hOldBitmap ) );
        Assert( hBitmap == m_hBitmap ,L"");
        ::DeleteDC( m_hDC );
        m_hDC = NULL;
    }
}


BOOL CuImageWnd::StretchBlt( HDC hDestDC, int xDest, int yDest, 
    int nDestWidth, int nDestHeight, int xSrc, int ySrc, int nSrcWidth, 
    int nSrcHeight, DWORD dwROP ) 
{

    BOOL bResult;

    Assert( m_hBitmap != NULL, L"" );
    Assert( hDestDC != NULL, L"" );

    HDC hDC = this->GetDC();

    bResult = ::StretchBlt( hDestDC, xDest, yDest, nDestWidth, nDestHeight, hDC,
        xSrc, ySrc, nSrcWidth, nSrcHeight, dwROP );

    this->ReleaseDC();

    return( bResult );

}


BOOL CuImageWnd::BitBlt( HDC hDestDC, int xDest, int yDest, int nDestWidth, 
    int nDestHeight, int xSrc, int ySrc, DWORD dwROP )
{
    BOOL bResult;
 
    Assert( m_hBitmap != NULL, L"");
    Assert( hDestDC != NULL, L"");

    GetDC();

    bResult = ::BitBlt( hDestDC, xDest, yDest, nDestWidth, nDestHeight, m_hDC, 
        xSrc, ySrc, dwROP );

    ReleaseDC();

    return( bResult );
}

CuImageWnd::operator HBITMAP() const
    { return m_hBitmap; }

支援Windows 專用的部份函式型別轉換: HDC HBITMAP 當然還有最重要的 點陣資料集