// Takes a snapshot of the specified processes
// CuToolhelp.h
class CuToolhelp
{
HANDLE m_hSnapshot;
public:
CuToolhelp();
virtual ~CuToolhelp();
BOOL CreateSnapshot(DWORD dwFlags, DWORD dwProcessID = 0);
void CloseSnapshot();
BOOL ProcessFirst(PPROCESSENTRY32 ppe) const;
BOOL ProcessNext(PPROCESSENTRY32 ppe) const;
BOOL ProcessFind(DWORD dwProcessID, PPROCESSENTRY32 ppe) ;
BOOL ProcessFind(wstring strExeFile, PPROCESSENTRY32 ppe) ;
};
// CuToolhelp.cpp
CuToolhelp::CuToolhelp()
:m_hSnapshot(INVALID_HANDLE_VALUE)
{
}
CuToolhelp::~CuToolhelp()
{
CloseSnapshot();
}
BOOL CuToolhelp::CreateSnapshot(DWORD dwFlags, DWORD dwProcessID)
{
CloseSnapshot();
if( dwFlags == 0 )
{
m_hSnapshot = INVALID_HANDLE_VALUE;
}
else
{
m_hSnapshot = CreateToolhelp32Snapshot(dwFlags, dwProcessID);
}
return (m_hSnapshot != INVALID_HANDLE_VALUE);
}
void CuToolhelp::CloseSnapshot()
{
if( m_hSnapshot != INVALID_HANDLE_VALUE )
CloseToolhelp32Snapshot(m_hSnapshot);
}
BOOL CuToolhelp::ProcessFirst(PPROCESSENTRY32 ppe) const
{
BOOL fOk = ::Process32First(m_hSnapshot, ppe);
// Remove the "[ System Process]" (PID = 0)
if( fOk && (ppe->th32ProcessID == 0 ))
fOk = ProcessNext(ppe);
return (fOk);
}
BOOL CuToolhelp::ProcessNext(PPROCESSENTRY32 ppe) const
{
BOOL fOk = ::Process32Next(m_hSnapshot, ppe);
// Remove the "[ System Process]" (PID = 0)
if( fOk && (ppe->th32ProcessID == 0 ))
fOk = ProcessNext(ppe);
return (fOk);
}
BOOL CuToolhelp::ProcessFind(DWORD dwProcessID, PPROCESSENTRY32 ppe)
{
BOOL bFound = FALSE;
for( BOOL fOk = ProcessFirst(ppe); fOk; fOk = ProcessNext(ppe) )
{
bFound = ( ppe->th32ProcessID == dwProcessID );
if( bFound )
break;
}
return (bFound);
}
BOOL CuToolhelp::ProcessFind(wstring strExeFile, PPROCESSENTRY32 ppe)
{
BOOL bFound = FALSE;
for( BOOL fOk = ProcessFirst(ppe); fOk; fOk = ProcessNext(ppe) )
{
bFound = (strExeFile == ppe->szExeFile);
if( bFound )
break;
}
return (bFound);
}
2010年1月31日 星期日
CuToolhelp - Takes a snapshot of the specified processes
2010年1月30日 星期六
TuPowerNotification -
//
class PowerNotificationTest
{
private:
TuPowerNotification<PowerNotificationTest> uPowerNotification;
public:
PowerNotificationTest() {}
~PowerNotificationTest() {}
void Init()
{
//初始化 TuPowerNotification
uPowerNotification.CombineElement(this, PowerNotificationTest::PowerNotify);
uPowerNotification.RequestPowerNotifications();
}
void PowerNotify(PPOWER_BROADCAST ppower_broadcast)
{
switch(ppower_broadcast->Message)
{
//取得 power status
case PBT_TRANSITION:
break;
case PBT_RESUME:
break;
case PBT_POWERSTATUSCHANGE:
break;
case PBT_POWERINFOCHANGE:
break;
}
}
// TuPowerNotification.h
template <typename T>
class TuPowerNotification : public CuPowerNotification
{
typedef void ( T::*POWER_NOTIFICATION_PROC)(PPOWER_BROADCAST ppower_broadcast);
POWER_NOTIFICATION_PROC m_fpPowerNotificationProc;
T *m_pElement;
public:
TuPowerNotification();
~TuPowerNotification();
void CombineElement(T *pElement, POWER_NOTIFICATION_PROC fpTimeOutProc);
virtual void OnPowerNotification(PPOWER_BROADCAST ppower_broadcast);
};
template <typename T>
TuPowerNotification<T>::TuPowerNotification()
:m_fpPowerNotificationProc(NULL)
,m_pElement(NULL)
{
}
template <typename T>
TuPowerNotification<T>::~TuPowerNotification()
{
}
template <typename T>
void TuPowerNotification<T>::OnPowerNotification(PPOWER_BROADCAST ppower_broadcast)
{
if(m_fpPowerNotificationProc)
(m_pElement->*m_fpPowerNotificationProc)(ppower_broadcast);
}
template <typename T>
void TuPowerNotification<T>::CombineElement(T *pElement, POWER_NOTIFICATION_PROC fpTimeOutProc)
{
m_pElement = pElement;
m_fpPowerNotificationProc = fpTimeOutProc;
}
2010年1月29日 星期五
CuFileLex - 文字檔剖析
// config.sys
--------------------------------------------
從某一隻ASE檔載入器中抓出來的,
CuFileLex 跟CuStringList 相比, 能載入較多格式的文字串, 組合後可以使用更豐富的設定檔
上面有兩大段分別支援一般文字檔跟UNICODE文字檔, 很顯示需要重構! 現在沒打算重構!
重構時間點在何時呢? 在他出錯的時後, 或是下次程式碼"review"的時後!
--------------------------------------------
TOTAL_ELEMENT_NUM 8
ELEMENT_NUM 1
ELEMENT_TYPE "element"
ELEMENT_NAME "background"
ELEMENT_POINT 0 0
ELEMENT_NEEDALPHA 0
TOTAL_PHOTO_NUM 1
PHOTO_NAME "media_bg.bmp" 4
ELEMENT_END
ELEMENT_NUM 2
ELEMENT_TYPE "button"
ELEMENT_NAME "close"
ELEMENT_POINT 3 3
ELEMENT_NEEDALPHA 1
TOTAL_PHOTO_NUM 4
PHOTO_NAME "close.bmp" 0
PHOTO_NAME "close_alpha.bmp" 1
PHOTO_NAME "close_down.bmp" 2
PHOTO_NAME "close_down_alpha.bmp" 3
ELEMENT_END
BUTTON_END
ELEMENT_NUM 3
ELEMENT_TYPE "commandbt"
ELEMENT_NAME "goto-photo"
ELEMENT_POINT 208 85
ELEMENT_NEEDALPHA 1
TOTAL_PHOTO_NUM 4
PHOTO_NAME "photoviewer_Icon.bmp" 13
PHOTO_NAME "photoviewer_Icon_alpha.bmp" 14
PHOTO_NAME "photoviewer_animation01.bmp" 15
PHOTO_NAME "photoviewer_animation01_alpha.bmp" 16
ELEMENT_END
BUTTON_END
COMMANDBT_ACTIVE_NAME "photoviewv350.exe"
COMMANDBT_END
ELEMENT_NUM 4
ELEMENT_TYPE "commandbt"
ELEMENT_NAME "goto-music"
ELEMENT_POINT 14 85
ELEMENT_NEEDALPHA 1
TOTAL_PHOTO_NUM 4
PHOTO_NAME "music_Icon.bmp" 9
PHOTO_NAME "music_Icon_alpha.bmp" 10
PHOTO_NAME "music_animation01.bmp" 11
PHOTO_NAME "music_animation01_alpha.bmp" 12
ELEMENT_END
BUTTON_END
COMMANDBT_ACTIVE_NAME "musicv350.exe"
COMMANDBT_END
ELEMENT_NUM 5
ELEMENT_TYPE "commandbt"
ELEMENT_NAME "goto-video"
ELEMENT_POINT 113 85
ELEMENT_NEEDALPHA 1
TOTAL_PHOTO_NUM 4
PHOTO_NAME "movie_Icon.bmp" 5
PHOTO_NAME "movie_Icon_alpha.bmp" 6
PHOTO_NAME "movie_animation01.bmp" 7
PHOTO_NAME "movie_animation01_alpha.bmp" 8
ELEMENT_END
BUTTON_END
COMMANDBT_ACTIVE_NAME "video\videov350.exe"
COMMANDBT_END
ELEMENT_NUM 6
ELEMENT_TYPE "statictext"
"PhotoView"
"text-photoview"
208 180 98 30
12
255 255 255
ELEMENT_NUM 7
ELEMENT_TYPE "statictext"
"Music"
"text-music"
14 180 98 30
12
255 255 255
ELEMENT_NUM 8
ELEMENT_TYPE "statictext"
"Video"
"text-Video"
113 180 98 30
12
255 255 255
//
// CuFileLex.h
class CuFileLex
{
BOOL m_bUnicode;
BOOL _IsUnicodeFile();
int _lexw(void);
int _lexa(void);
CuFile m_File;
public:
CuFileLex(void);
~CuFileLex(void);
BOOL Open( LPCSTR lpszFileName, LPCSTR lpszOpenMode);
virtual BOOL Open( LPCTSTR lpszFileName, LPCTSTR lpszOpenMode);
int _type; // 最後呼叫 _lex() 的字串類型
wstring _text; // 將讀到的字串 放到這裡
enum {UNKNOW = 0, INTEGER = 1, FLOAT, SYMBOL, INDEX, STRING, NODE, BLOCKSTART, BLOCKEND};
// 讀一段字 並分析字串 傳回字串類型
int _lex(void);
void _readInt(int &i);
void _readInt3(int i[3]);
void _readInt4(int i[4]);
void _readFloat(float &f);
void _readFloat3(float f[3]);
void _readSymbol(wstring &str);
void _readIndex();
void _readString(wstring &str);
void _readNode();
void _readBlockStart();
int _skip();
};
// CuFileLex.cpp
CuFileLex::CuFileLex(void) : _type(UNKNOW)
{
}
CuFileLex::~CuFileLex(void)
{
}
int CuFileLex::_lex(void)
{
// static
// char check[] = "-0123456789._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"{}:*";
//"12345678901234567890123456789012345678901234567890123456789012345 678901234
//"0 1 2 3 4 5 6 7
// 1~11 = INTEGER
// 12 = FLOAT
// 13~65 = SYMBOL
// 69 = INDEX
// 66 = STRING
// 70 = NODE
// 67 = BLOCKSTART
// 68 = BLOCKEND
// 字串分析的權位 左邊比較低 右邊比較高
// enum {UNKNOW = 0, INTEGER = 1, FLOAT, SYMBOL, INDEX, STRING, NODE, BLOCKSTART, BLOCKEND};
_text = L"";
int result;
int current_type = 0;
int type = UNKNOW; // 分析字串的類型
bool baString = false; // 當正在讀字串時 會一直讀到 下一個 '\"'
// 排除前置空白 換行 定位 字元
do
{
result = m_File.get();
}while( result != EOF && (result == 9 || result == 32 || result == 13 || result == 10 ));
while(result != EOF)
{
// ---------------+---------------
// 字串種類判段
if( baString )
{
if( result == 0x22 )
baString = !baString;
}else if( (result >= 0x41 && result <= 0x5a) ||
(result >= 0x61 && result <= 0x7a) ||
(result == 0x5f) )
current_type = SYMBOL;
else if( (result >= 0x30 && result <= 0x39) || result == 0x2d )
current_type = INTEGER;
else
{
switch( result )
{
case 0x2e:
current_type = FLOAT;
break;
case 0x3a:
current_type = INDEX;
break;
case 0x22:
current_type = STRING;
baString = !baString;
break;
case 0x2a:
current_type = NODE;
break;
case 0x7b:
current_type = BLOCKSTART;
break;
case 0x7d:
current_type = BLOCKEND;
break;
default:
{
_type = type;
return type;
}
}
}
if( type < current_type )
type = current_type;
// ---------------+---------------
_text += result;
result = m_File.get();
}
_type = type;
return type;
}
int CuFileLex::_lexw(void)
{
// static
// TCHAR check[] = L"-0123456789._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"{}:*";
//"12345678901234567890123456789012345678901234567890123456789012345 678901234
//"0 1 2 3 4 5 6 7
// 1~11 = INTEGER
// 12 = FLOAT
// 13~65 = SYMBOL
// 69 = INDEX
// 66 = STRING
// 70 = NODE
// 67 = BLOCKSTART
// 68 = BLOCKEND
// 字串分析的權位 左邊比較低 右邊比較高
// enum {UNKNOW = 0, INTEGER = 1, FLOAT, SYMBOL, INDEX, STRING, NODE, BLOCKSTART, BLOCKEND};
_text = L"";
WORD result;
int current_type = 0;
int type = UNKNOW; // 分析字串的類型
bool baString = false; // 當正在讀字串時 會一直讀到 下一個 '\"'
int nSizeT = 0;
// 排除前置空白 換行 定位 字元
do
{
nSizeT = m_File.Read(&result, sizeof(result) );
}while( nSizeT != 0 && (result != EOF && result == 9 || result == 32 || result == 13 || result == 10 ));
while(result != EOF && nSizeT != 0 )
{
// ---------------+---------------
// 字串種類判段
if( baString )
{
if( result == 0x22 )
baString = !baString;
}else if( (result >= 0x41 && result <= 0x5a) ||
(result >= 0x61 && result <= 0x7a) ||
(result == 0x5f) )
current_type = SYMBOL;
else if( (result >= 0x30 && result <= 0x39) || result == 0x2d )
current_type = INTEGER;
else
{
switch( result )
{
case 0x2e:
current_type = FLOAT;
break;
case 0x3a:
current_type = INDEX;
break;
case 0x22:
current_type = STRING;
baString = !baString;
break;
case 0x2a:
current_type = NODE;
break;
case 0x7b:
current_type = BLOCKSTART;
break;
case 0x7d:
current_type = BLOCKEND;
break;
default:
{
_type = type;
return type;
}
}
}
if( type < current_type )
type = current_type;
// ---------------+---------------
_text += result;
nSizeT = m_File.Read(&result, sizeof(result) );
}
_type = type;
return type;
}
// 讀一段字 並分析字串 傳回字串類型
int CuFileLex::_lex(void)
{
if( m_bUnicode )
return _lexw();
else
return _lexa();
return m_bUnicode ? _lexw() : _lexa();
}
// 讀一段字 並分析字串 傳回字串類型
void CuFileLex::_readInt(int &i)
{
_lex();
Assert( _type == INTEGER , L"CuFileLex::_readInt: Expected an integer\n");
swscanf(_text.c_str(), L"%i", &i);
}
void CuFileLex::_readInt3(int i[3])
{
_readInt(i[0]);
_readInt(i[1]);
_readInt(i[2]);
}
void CuFileLex::_readInt4(int i[4])
{
_readInt(i[0]);
_readInt(i[1]);
_readInt(i[2]);
_readInt(i[3]);
}
void CuFileLex::_readFloat(float &f)
{
_lex();
Assert( _type == FLOAT , L"CuFileLex::_readFloat: Expected an float\n");
swscanf(_text.c_str(), L"%f", &f);
}
void CuFileLex::_readFloat3(float f[3])
{
_readFloat(f[0]);
_readFloat(f[1]);
_readFloat(f[2]);
}
void CuFileLex::_readSymbol(wstring &str)
{
_lex();
Assert( _type == SYMBOL , L"CuFileLex::_readSymbol: Expected a symbol\n");
str = _text;
}
void CuFileLex::_readIndex()
{
_lex();
Assert( _type == INDEX , L"CuFileLex::_readIndex: Expected a index\n");
}
void CuFileLex::_readString(wstring &str)
{
_lex();
Assert( _type == STRING , L"CuFileLex::_readString: Expected a string\n");
// 脫溢字串兩頭的 雙引號
if( _text.size() != 0 )
str.assign( _text, 1, _text.size() - 2);
}
void CuFileLex::_readNode()
{
_lex();
Assert( _type == NODE , L"CuFileLex::_readNode: Expected a node\n");
}
void CuFileLex::_readBlockStart()
{
_lex();
Assert( _type == BLOCKSTART , L"CuFileLex::_readBlockStart: Expected an open brace\n");
}
int CuFileLex::_skip()
{
int nextToken;
int depth = 0;
char neednext = 1;
do {
if(neednext)
nextToken = _lex();
else
neednext = 1;
if(nextToken == BLOCKSTART)
depth++;
if(nextToken == BLOCKEND)
if(depth > 0) {
/*printf("skipping %s\n", ASE_text);*/
depth--;
nextToken = _lex();
neednext = 0;
}
/*printf("skipping %s (%i) (depth %i)\n", ASE_text, ASE_linenum, depth);*/
} while(nextToken && (depth || (nextToken != NODE && nextToken != BLOCKEND)));
/*printf("done (got %s)\n", ASE_text);*/
return nextToken;
}
BOOL CuFileLex::_IsUnicodeFile()
{
FILE* pFileStream = m_File.GetFILE();
WORD result = 0;
fseek( pFileStream, 0, SEEK_SET);
int nSizeT = m_File.Read(&result, sizeof(result) );
if( result != 0xfeff )
{
fseek( pFileStream, 0, SEEK_SET);
}
return (result == 0xfeff);
}
BOOL CuFileLex::Open( LPCSTR lpszFileName, LPCSTR lpszOpenMode)
{
string strFileName = lpszFileName;
string strOpenMode = lpszOpenMode;
wstring wstrFileName(strFileName.begin(), strFileName.end());
wstring wstrOpenMode(strOpenMode.begin(), strOpenMode.end());
return Open(wstrFileName.c_str(),wstrOpenMode.c_str() );
}
BOOL CuFileLex::Open( LPCTSTR lpszFileName, LPCTSTR lpszOpenMode)
{
BOOL bResult = m_File.Open(lpszFileName, lpszOpenMode);
Assert(bResult != FALSE, L"can't open file" );
Assert(bResult != FALSE, const_cast<TCHAR *>(lpszFileName) );
if( bResult == FALSE )
return FALSE;
m_bUnicode = this->_IsUnicodeFile();
if( m_bUnicode )
{
if( wcscmp (lpszOpenMode , L"r") == 0 )
{
lpszOpenMode = L"rb";
m_File.Close();
bResult = m_File.Open(lpszFileName, lpszOpenMode);
m_bUnicode = this->_IsUnicodeFile();
}
}
else
{
m_File.Close();
bResult = m_File.Open(lpszFileName, lpszOpenMode);
}
return bResult;
}
從某一隻ASE檔載入器中抓出來的,
CuFileLex 跟CuStringList 相比, 能載入較多格式的文字串, 組合後可以使用更豐富的設定檔
上面有兩大段分別支援一般文字檔跟UNICODE文字檔, 很顯示需要重構! 現在沒打算重構!
重構時間點在何時呢? 在他出錯的時後, 或是下次程式碼"review"的時後!
2010年1月28日 星期四
CuMicroTime - the current timestamp with microseconds.
// the current timestamp with microseconds.
// CuMicroTime.php
class CuMicroTime {
var $usec;
var $sec;
function CuMicroTime(/* CuMicroTime */ $MicroTime = null) {
if( $this->CheckClassType($MicroTime) )
{
$this->usec = $MicroTime->usec;
$this->sec = $MicroTime->sec;
}
else
{
list($this->usec, $this->sec) = explode(" ", microtime());
}
}
function Dec( /* CuMicroTime */ $MicroTime)
{
if( CheckClassType($MicroTime) )
return NULL;
$usec = (float)$this->usec - (float)$MicroTime->usec;
$sec = $this->sec - $MicroTime->sec;
$usec = substr($usec, 1);
return $sec.$usec;
}
function CheckClassType($MicroTime)
{
if( gettype($MicroTime) != 'object' || get_class($MicroTime) != "cumicrotime" )
return false;
else
return true;
}
}
2010年1月27日 星期三
CuShellExecuteEx - Performs an operation on a specified file.
// Performs an operation on a specified file.
// CuShellExecuteEx.h
class CuShellExecuteEx
{
public:
void SetExecuteFile(wstring strFile, BOOL bAutoModuleFile = FALSE);
BOOL OnShellExecuteEx();
SHELLEXECUTEINFO m_sei;
wstring m_strExecuteFile;
CuShellExecuteEx();
~CuShellExecuteEx();
};
// CuShellExecuteEx.cpp
CuShellExecuteEx::CuShellExecuteEx()
{
m_sei.cbSize = sizeof(SHELLEXECUTEINFO);
m_sei.fMask = 0;
m_sei.hwnd = NULL;
m_sei.lpVerb = TEXT("open");
m_sei.lpFile = NULL;
m_sei.lpParameters = NULL;
m_sei.lpDirectory = NULL;
m_sei.nShow = SW_SHOW;
m_sei.hInstApp = NULL;
}
CuShellExecuteEx::~CuShellExecuteEx()
{
}
BOOL CuShellExecuteEx::OnShellExecuteEx()
{
return ::ShellExecuteEx(&m_sei);
}
void CuShellExecuteEx::SetExecuteFile(wstring strFile, BOOL bAutoModuleFile /*= FALSE*/)
{
if( bAutoModuleFile )
{
CuModuleFile mf;
strFile = mf.GetModuleFileName(strFile);
}
m_strExecuteFile = strFile;
m_sei.lpFile = m_strExecuteFile.c_str();
}
2010年1月26日 星期二
CuModuleFile - Retrieves the fully-qualified path for the file that contains the onwer module.
// Retrieves the fully-qualified path for the file that contains the onwer module.
// CuModuleFile.h
class CuModuleFile //: public IuModuleFile
{
public:
CuModuleFile();
~CuModuleFile();
wstring GetModuleFileName(wstring strFileName);
// 傳入空的字串 會傳回執行檔檔名
wstring GetUnModuleFileName(wstring strFileName = L"");
wstring CutRFind(wstring str, TCHAR ch);
};
// CuModuleFile.cpp
CuModuleFile::CuModuleFile()
{
}
CuModuleFile::~CuModuleFile()
{
}
//////////////////////////////////////////////////////////////////////
// 函式名稱:GetModuleFileName
// 函式說明:將strFileName 前面加上 主執行緒執行檔同目錄的路徑
// 使用範例:
// 啟動 C:\Documents and Settings\Eric Wang\My Documents\Work\test.exe
// strFileName = L"sample.ini"
// str = mf.GetModuleFileName(strFileName);
// Access(str = L"C:\Documents and Settings\Eric Wang\My Documents\Work\sample.ini");
//////////////////////////////////////////////////////////////////////
wstring CuModuleFile::GetModuleFileName(wstring strFileName)
{
wstring filename;
wstring strFile = strFileName;
wstring::size_type npos = -1;
wstring::size_type indexCh1a;
int nCount = 0;
while ( (indexCh1a = strFile.find(L"..\\")) != npos )
{
nCount++;
strFile = strFile.substr(indexCh1a + 3);
}
TCHAR szModule[255] = L"";
LPTSTR psz;
::GetModuleFileName(GetModuleHandle(NULL), szModule, MAX_PATH);
do
{
psz = wcsrchr(szModule, L'\\');
if (psz)
{
*psz = L'\0';
}
}while( nCount-- );
wcscat(szModule, L"\\");
wcscat(szModule, strFile.c_str());
return szModule;
}
//////////////////////////////////////////////////////////////////////
// 函式名稱:GetUnModuleFileName
// 函式說明:函路徑的檔名前面的路徑清掉, strFileName = NULL 時 會傳回主執行緒的執行檔檔名
// 使用範例:
// strFileName = L"C:\\Documents and Settings\\Eric Wang\My Documents\\Work\\temp.txt"
// str = mf.GetUnModuleFileName(strFileName);
// Access(str = L"temp.txt");
//////////////////////////////////////////////////////////////////////
wstring CuModuleFile::GetUnModuleFileName(wstring strFileName /* = L"" */)
{
wstring filename;
wstring strFull;
if( strFileName.size() == 0 )
{
TCHAR szModule[255] = L"";
::GetModuleFileName(GetModuleHandle(NULL), szModule, MAX_PATH);
strFull = szModule;
}
else
strFull = strFileName;
static const wstring::size_type npos = -1;
wstring::size_type indexCh1a;
indexCh1a = strFull.rfind('\\');
if( indexCh1a != npos )
filename = strFull.substr(indexCh1a + 1);
else
filename = strFull;
return filename;
}
//////////////////////////////////////////////////////////////////////
// 函式名稱: CutRFind
// 函式說明: 去掉 ch 右邊的字串
// 使用範例:
// str = text.txt
// str2 = mf.GetRFind(str, '.');
// Assert( str2 = L"text");
//////////////////////////////////////////////////////////////////////
wstring CuModuleFile::CutRFind(wstring str, TCHAR ch)
{
wstring strResult;
static const wstring::size_type npos = -1;
wstring::size_type indexCh1a;
indexCh1a = str.rfind(ch);
if( indexCh1a != npos )
strResult = str.substr(0, indexCh1a);
else
strResult = str;
return strResult;
}
2010年1月25日 星期一
CuVolume - sets the volume of a waveform output device.
// sets the volume of a waveform output device.
DWORD dw, dw2;
// dw : 0x0000~0xffff
// dw2: 0~MAX
CuVolume Volume;
dw = Volume.GetVolume();
dw2 = Volume.GetVolume(MAX);
Volume.SetVolume(dw);
Volume.SetVolume(dw2, MAX);
Volume.IncVolume(MAX);
Volume.DecVolume(MAX);
// CuVolume.h
class CuVolume
{
BOOL m_bMute;
unsigned long m_nVolume;
//////////////////////////////////////////////////////////////////////
//
CuDllManager dll;
typedef DWORD (*pAudio) ();
pAudio pProc;
void UpdateVolumeFromRegistry();
//////////////////////////////////////////////////////////////////////
public:
CuVolume();
virtual ~CuVolume();
void IncVolume(int nMax);
void DecVolume(int nMax);
BOOL GetMute(void){ return m_bMute; }
BOOL SetMute(BOOL b);
// 直接指定值 v = 0 ~ 0xffff
BOOL SetVolume(unsigned long v);
unsigned long GetVolume(void);
// 正規化過的值 指定max Ex: v = 50 , nMAx = 100 , 會設定 50%
// v = 1, nMax = 5, 會設定 20%
BOOL SetVolume(int v, int nMax);
// 取回正規化過的值
int GetVolume(int nMax);
};
// CuVolume.cpp
#define MAX_VALUES 0xffff
void CuVolume::UpdateVolumeFromRegistry()
{
if( pProc )
pProc();
}
CuVolume::CuVolume()
:m_bMute(FALSE)
{
GetVolume();
dll.LoadLibrary(_T("coredll.dll"));
pProc = (pAudio)dll.GetProcAddress(_T("AudioUpdateFromRegistry"));
}
CuVolume::~CuVolume()
{
}
BOOL CuVolume::SetMute(BOOL b)
{
static unsigned long nVolume = GetVolume();
m_bMute = b;
if (m_bMute)
{
nVolume = GetVolume();
SetVolume(0);
}
else
{
SetVolume(nVolume);
}
return TRUE;
}
BOOL CuVolume::SetVolume(unsigned long v)
{
m_nVolume = v;
waveOutSetVolume(NULL, 0x10001 * v) ;
CReg reg(HKEY_CURRENT_USER, _T("ControlPanel\\Volume"));
reg.SetDW(_T("Volume"), 0x10001 * v);
UpdateVolumeFromRegistry();
return TRUE;
}
unsigned long CuVolume::GetVolume(void)
{
unsigned long Value;
if (waveOutGetVolume(NULL,&Value) == MMSYSERR_NOERROR)
{
m_nVolume = ( (LOWORD(Value)+HIWORD(Value)) ) / 2 ;
}
return m_nVolume;
}
BOOL CuVolume::SetVolume(int v, int nMax)
{
DWORD Value = v * MAX_VALUES / nMax;
SetVolume(Value);
return TRUE;
}
int CuVolume::GetVolume(int nMax)
{
unsigned long Value;
Value = (float)nMax * ((float)GetVolume() + 600) / (float)MAX_VALUES;
return Value;
}
void CuVolume::IncVolume(int nMax)
{
if( GetMute() )
SetMute(FALSE);
unsigned long offset_Value = (float)MAX_VALUES / nMax;
unsigned long Value = (float)GetVolume();
Value += offset_Value;
if( Value > MAX_VALUES)
Value = MAX_VALUES;
SetVolume(Value);
}
void CuVolume::DecVolume(int nMax)
{
if( GetMute() )
SetMute(FALSE);
float offset_Value = (float)MAX_VALUES / nMax;
float Value = (float)GetVolume();
if( Value <= offset_Value)
Value = 0;
else
Value -= offset_Value;
SetVolume(Value);
}
2010年1月24日 星期日
CuPowerNotification - to register for power notification events.
// to register for power notification events.
// CuPowerNotification.h
class CuPowerNotification
{
HANDLE m_hRequestPowerNotifications;
CuWinThread *m_pWinThread;
CuMsgQueue m_MsgQueue;
public:
virtual void OnPowerNotification(PPOWER_BROADCAST ppower_broadcast){};
BOOL StopPowerNotifications();
HANDLE RequestPowerNotifications(DWORD Flags = POWER_NOTIFY_ALL, wstring strMsgQueueName = L"");
CuPowerNotification();
virtual ~CuPowerNotification();
private:
static DWORD Process(LPVOID lpVoid);
};
// CuPowerNotification.cpp
#define QUEUE_ENTRIES 3
#define QUEUE_SIZE ( QUEUE_ENTRIES * (sizeof(POWER_BROADCAST) + sizeof(POWER_BROADCAST_POWER_INFO)) )
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CuPowerNotification::CuPowerNotification()
:m_hRequestPowerNotifications(NULL)
,m_pWinThread(NULL)
{
}
CuPowerNotification::~CuPowerNotification()
{
StopPowerNotifications();
}
HANDLE CuPowerNotification::RequestPowerNotifications(
DWORD Flags /* = POWER_NOTIFY_ALL */
, wstring strMsgQueueName /*= L""*/)
{
StopPowerNotifications();
MSGQUEUEOPTIONS MsgQueueOptions;
memset(&MsgQueueOptions , 0, sizeof( MsgQueueOptions));
MsgQueueOptions.dwSize = sizeof( MSGQUEUEOPTIONS );
MsgQueueOptions.dwFlags = 0 ;
MsgQueueOptions.dwMaxMessages = QUEUE_ENTRIES;
MsgQueueOptions.cbMaxMessage = QUEUE_SIZE;
MsgQueueOptions.bReadAccess = TRUE ;
//TCHAR *pszMsgQueue = strMsgQueueName.c_str();
TCHAR szMsgQueueName[64] = L"";
if( strMsgQueueName.empty() )
wsprintf( szMsgQueueName, L"%x", (int)this );
else
wsprintf( szMsgQueueName, L"%s", strMsgQueueName.c_str());
m_MsgQueue.CreateMsgQueue(szMsgQueueName, &MsgQueueOptions);
m_hRequestPowerNotifications = ::RequestPowerNotifications( m_MsgQueue, Flags );
if( m_hRequestPowerNotifications )
m_pWinThread = _BeginThread((_THREADPROC)CuPowerNotification::Process,
(LPVOID)this);
return m_hRequestPowerNotifications;
}
BOOL CuPowerNotification::StopPowerNotifications()
{
if( m_pWinThread )
m_pWinThread->Delete();
m_pWinThread = NULL;
return ::StopPowerNotifications(m_hRequestPowerNotifications);
}
DWORD CuPowerNotification::Process(LPVOID lpVoid)
{
CuPowerNotification *pPowerNotification = (CuPowerNotification *)lpVoid;
static BYTE buf[QUEUE_SIZE];
static unsigned long nRead = 0;
static unsigned long flags = 0;
DWORD dwResult;
while(1)
{
dwResult = WaitForSingleObject(pPowerNotification->m_MsgQueue, INFINITE);
if( dwResult == WAIT_OBJECT_0 )
{
memset(&buf , 0, QUEUE_SIZE);
dwResult = pPowerNotification->m_MsgQueue.ReadMsgQueue(
&buf, QUEUE_SIZE, &nRead, INFINITE, &flags);
if( dwResult != FALSE )
pPowerNotification->OnPowerNotification((PPOWER_BROADCAST)buf);
}
}
return 0;
}
2010年1月23日 星期六
TuWinTimer - creates a timer with the specified time-out value.
// creates a timer with the specified time-out value.
class CuMyClass
{
TuWinTimer<CuMyClass> m_winTimer;
public:
void OnMyFunction(void);
void Init(void);
};
void CuMyClass::Init()
{
m_winTimer.Init(1000);
m_winTimer.CombineElement(this, &CuMyClass::OnMyFunction, g_hWnd);
...
m_winTimer.OnStardTime();
}
void CuMyClass::OnMyFunction(void)
{
...
m_winTimer.OnStopTime();
}
// TuWinTimer.h
template <typename T>
class TuWinTimer
UINT m_uElapse;
T *m_pElement;
HWND m_hWnd;
typedef void ( T::*ELEMENTTIME_TIMEOUTPROC)(void);
ELEMENTTIME_TIMEOUTPROC m_fpTimeOutProc;
static VOID CALLBACK TuWinTimerTimerProc( HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime
)
{
TuWinTimer<T> *pElement = (TuWinTimer<T>*)idEvent;
T *pActiveElement = pElement->m_pElement;
(pActiveElement->*(pElement->m_fpTimeOutProc))();
}
public:
TuWinTimer();
~TuWinTimer();
void Init(UINT uElapse);
void CombineElement(T *pElement, ELEMENTTIME_TIMEOUTPROC fpTimeOutProc, HWND hWnd);
void OnStardTime();
void OnStopTime();
};
template <typename T>
TuWinTimer<T>::TuWinTimer()
:m_uElapse(0)
,m_pElement(NULL)
,m_fpTimeOutProc(NULL)
,m_hWnd(NULL)
{
}
template <typename T>
TuWinTimer<T>::~TuWinTimer()
{
OnStopTime();
}
template <typename T>
void TuWinTimer<T>::Init(UINT uElapse)
{
m_uElapse = uElapse;
}
template <typename T>
void TuWinTimer<T>::OnStardTime()
{
OnStopTime();
::SetTimer(m_hWnd, (UINT)this, m_uElapse, TuWinTimer<T>::TuWinTimerTimerProc );
}
template <typename T>
void TuWinTimer<T>::OnStopTime()
{
::KillTimer(m_hWnd, (UINT)this);
}
template <typename T>
void TuWinTimer<T>::CombineElement(T *pElement, ELEMENTTIME_TIMEOUTPROC fpTimeOutProc, HWND hWnd)
{
m_pElement = pElement;
m_fpTimeOutProc = fpTimeOutProc;
Assert( hWnd != NULL , L"Error : hWnd == NULL");
m_hWnd = hWnd;
}
2010年1月22日 星期五
CuMsgQueue - pass information between different programs.
// pass information between different programs.
//
MSGQUEUEOPTIONS msg_queue_options;
msg_queue_options.dwSize = sizeof(MSGQUEUEOPTIONS);
msg_queue_options.dwMaxMessages = 0;
msg_queue_options.cbMaxMessage = TEST_BUFFER_SIZE;
msg_queue_options.bReadAccess = TRUE;
msg_queue_options.dwFlags = MSGQUEUE_NOPRECOMMIT;
MsgReadQueue.CreateMsgQueue(lpszName, &msg_queue_options);
//
wchar_t test_text[TEST_BUFFER_SIZE];
ret = WaitForSingleObject(MsgReadQueue, INFINITE);
if (ret == WAIT_OBJECT_0) {
DWORD read_bytes;
DWORD flag;
MsgReadQueue.ReadMsgQueue(test_text, sizeof(wchar_t) * TEST_BUFFER_SIZE, &read_bytes, INFINITE, &flag);
}
// CuMsgQueue.h
class CuMsgQueue
{
HANDLE m_hCreateMsgQueue;
public:
BOOL ReadMsgQueue(LPVOID lpBuffer,
DWORD cbBufferSize,
LPDWORD lpNumberOfBytesRead,
DWORD dwTimeout,
DWORD* pdwFlags);
HANDLE CreateMsgQueue(LPWSTR lpszName,LPMSGQUEUEOPTIONS lpOptions);
BOOL CloseMsgQueue( );
operator HANDLE() const;
CuMsgQueue();
virtual ~CuMsgQueue();
};
// CuMsgQueue.cpp
CuMsgQueue::CuMsgQueue()
:m_hCreateMsgQueue(NULL)
{
}
CuMsgQueue::~CuMsgQueue()
{
CloseMsgQueue();
}
BOOL CuMsgQueue::CloseMsgQueue()
{
return ::CloseMsgQueue(m_hCreateMsgQueue);
}
HANDLE CuMsgQueue::CreateMsgQueue(LPWSTR lpszName, LPMSGQUEUEOPTIONS lpOptions)
{
CloseMsgQueue();
m_hCreateMsgQueue = ::CreateMsgQueue(lpszName, lpOptions);
return m_hCreateMsgQueue;
}
CuMsgQueue::operator HANDLE() const
{ return (HANDLE)(this == NULL ? NULL : m_hCreateMsgQueue); }
BOOL CuMsgQueue::ReadMsgQueue(LPVOID lpBuffer,
DWORD cbBufferSize,
LPDWORD lpNumberOfBytesRead,
DWORD dwTimeout,
DWORD* pdwFlags)
{
return ::ReadMsgQueue(m_hCreateMsgQueue, lpBuffer, cbBufferSize, lpNumberOfBytesRead, dwTimeout, pdwFlags);
}
像這種 MSGQUEUEOPTIONS msg_queue_options; 有結構設定的部份, 實在很想把他包到類別裡, 在使用函式參數傳遞,並且設定部份參數為預設值!
不僅使用起來美觀! 而且還不用特別去查結構!
2010年1月21日 星期四
CuTimer - specialized type of clock.
// specialized type of clock.
CuTimer _Timer;
while(1)
{
_Timer.Make_Tick_Data();
if( _Timer.GetTimeOut(9) )
....
_Timer.Tick_Data_Clear();
}
// CuTimer.h
class CuTimer
{
public:
BOOL GetTimeOut(int i); // table_1
void Make_Tick_Data();
void Tick_Data_Full();
void Tick_Data_Clear();
CuTimer();
~CuTimer();
private:
DWORD More_Time[20];
DWORD lastTickCount[20];
BYTE Time_move[20];
DWORD thisTickCount;
};
// CuTimer.cpp
CuTimer::CuTimer(void)
{
this->Tick_Data_Clear();
}
CuTimer::~CuTimer(void)
{
}
void CuTimer::Tick_Data_Clear()
{
memset( Time_move, 0, sizeof Time_move );
}
void CuTimer::Tick_Data_Full()
{
memset( Time_move, 1, sizeof Time_move );
}
void CuTimer::Make_Tick_Data()
{
static DWORD delay[20] = {
10, //0 , 1/100 sec 0.01
16, //1 , 1/60 sec 0.016
17, //2 , 1/56 sec 0.017
20, //3 , 1/48 sec 0.020
25, //4 , 1/40 sec 0.025
33, //5 , 1/30 sec 0.033
41, //6 , 1/24 sec 0.041
62, //7 , 1/16 sec 0.062
83, //8 , 1/12 sec 0.083
125, //9 , 1/8 sec 0.125
166, //10, 1/6 sec 0.166
250, //11, 1/4 sec 0.250
333, //12, 1/3 sec 0.333
500, //13, 1/2 sec 0.5
1000, //14, 1 sec
2000, //15, 2 sec
3000, //16, 3 sec
4000, //17, 4 sec
5000, //18, 5 sec
8000 //19, 8 sec
};
thisTickCount = GetTickCount();
for (int i = 0; i < 20; i++)
{
if( (thisTickCount - lastTickCount[i]) >= delay[i])
{
More_Time[i] = (thisTickCount - lastTickCount[i]) - delay[i];
lastTickCount[i] = thisTickCount;
if( More_Time[i] < 30 )
lastTickCount[i] -= More_Time[i];
Time_move[i]++;
}
}
}
BOOL CuTimer::GetTimeOut(int i)
{
return (BOOL)Time_move[i];
}
2010年1月20日 星期三
PHP : CDate
// CDate.php
class CDate {
function str2time($strStr, $strPattern)
{
// an array of the valide date characters, see: http://php.net/date#AEN21898
$arrCharacters = array(
'd', // day
'm', // month
'y', // year, 2 digits
'Y', // year, 4 digits
'H', // hours
'i', // minutes
's' // seconds
);
// transform the characters array to a string
$strCharacters = implode('', $arrCharacters);
// splits up the pattern by the date characters to get an array of the delimiters between the date characters
$arrDelimiters = preg_split('~['.$strCharacters.']~', $strPattern);
// transform the delimiters array to a string
$strDelimiters = quotemeta(implode('', array_unique($arrDelimiters)));
// splits up the date by the delimiters to get an array of the declaration
$arrStr = preg_split('~[' . $strDelimiters . ']~' , $strStr);
// splits up the pattern by the delimiters to get an array of the used characters
$arrPattern = preg_split('~['.$strDelimiters.']~', $strPattern);
// if the numbers of the two array are not the same, return false, because the cannot belong together
if (count($arrStr) !== count($arrPattern)) {
return false;
}
// creates a new array which has the keys from the $arrPattern array and the values from the $arrStr array
$arrTime = array();
for ($i = 0;$i < count($arrStr);$i++) {
$arrTime[$arrPattern[$i]] = $arrStr[$i];
}
// gernerates a 4 digit year declaration of a 2 digit one by using the current year
if (isset($arrTime['y']) && !isset($arrTime['Y'])) {
$arrTime['Y'] = substr(date('Y'), 0, 2) . $arrTime['y'];
}
// if a declaration is empty, it will be filled with the current date declaration
foreach ($arrCharacters as $strCharacter) {
if (empty($arrTime[$strCharacter])) {
$arrTime[$strCharacter] = date($strCharacter);
}
}
// checks if the date is a valide date
if (!checkdate($arrTime['m'], $arrTime['d'], $arrTime['Y'])) {
return false;
}
// generates the timestamp
$intTime = mktime($arrTime['H'], $arrTime['i'], $arrTime['s'], $arrTime['m'], $arrTime['d'], $arrTime['Y']);
// returns the timestamp
return $intTime;
} // end function str2time
}// end class CDate
雖然現在很少人在寫PHP用手動比對時間, 通常都交給SQL去驗證.
2010年1月19日 星期二
Assert - assertion
// An assertion statement specifies a condition that you expect to hold true at some particular point in your program.
Assert(m_hThread != NULL, _T("CuWinThread::ResumeThread m_hThread != NULL");
// uAssert.h
#if defined(_DEBUG)
#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
#define __WFILE__ WIDEN(__FILE__)
extern bool CustomAssertFunction( bool, TCHAR*, int, TCHAR*, bool*);
#if defined(_WINDOWS)
#define ASSERTPRESS { _asm { int 3 } }
#else
#define ASSERTPRESS {}
#endif // defined(_WINDOWS)
#define Assert( exp, description) \
{ static bool ignoreAlways = false; \
if( !ignoreAlways) { \
if( CustomAssertFunction( (int)(exp), description, __LINE__, __FILE__, &ignoreAlways) ) \
ASSERTPRESS \
} \
}
#define Verify(exp, description) Assert(exp, description)
#else
#define Assert(exp, description) ((void)0)
#define Verify(exp, description) ((void)(exp))
#endif // defined(_DEBUG)
// uAssert.cpp
// Return:
// true - Stop On Assert Line
// false - continue
bool CustomAssertFunction( bool bExp, TCHAR* strDesc, int iLine, TCHAR* strFilename, bool *ignoreAlways)
{
if( !bExp )
{
TCHAR strTitle[255] = TEXT("");
TCHAR strText[255] = TEXT("");
wsprintf(strTitle, TEXT("%s - %d"), strFilename, iLine);
wsprintf(strText, TEXT("%s \n Yes to Continue \n No to Break\n Cancle to Ignore Always"), strDesc);
int nRelease = MessageBox(NULL, strText, strTitle, MB_YESNOCANCEL);
switch( nRelease )
{
case 6:
return false;
break;
case 7:
return true;
break;
case 2:
*ignoreAlways = true;
break;
}
}
return false;
}
這個有擴充過, 使用 _asm { int 3 } 能停在Assert 那一行.
2010年1月18日 星期一
CuSocketFile - A CuFile object used for sending and receiving data across a network via Windows Sockets
// CuSocketFile - A CuFile object used for sending and receiving data across a network via Windows Sockets.
CuSocket sk;
CuSocketFile skFile(&sk);
CuFile *pFile = &skFile;
pFile->Write(...);
pFile->Read(...);
// CuSocketFile.h
class CuSocketFile : public CuFile
{
CuSocket* m_pSocket;
public:
CuSocketFile( CuSocket* pSocket);
~CuSocketFile();
public:
virtual int Write(const void* lpBuf, UINT nCount);
virtual int Read(void* lpBuf, UINT nCount);
};
// CuSocketFile.cpp
CuSocketFile::~CuSocketFile()
{
}
CuSocketFile::CuSocketFile(CuSocket *pSocket)
{
m_pSocket = pSocket;
}
// rc == SOCKET_ERROR 在外部在處理
int CuSocketFile::Read(void *lpBuf, UINT nCount)
{
if( lpBuf == NULL )
return 0;
return m_pSocket->Receive(lpBuf, nCount, 0);
}
int CuSocketFile::Write(const void *lpBuf, UINT nCount)
{
if( lpBuf == NULL )
return 0;
retrun m_pSocket->Send((const TCHAR*)lpBuf , nCount, 0);
}
使用繼承 public CuFile , 在對TheApp做多型, TheApp並不需要知道是LocalFile 還是 Remote Socket.這裡有個很特別的問題, CuFile 跟 CuSocketFile 除了介面相同外, 並沒有任何的程式碼相容.
因此需要繼承的並不是CuFile實體, 而是
class CuFile : public IuFile
class CuSocketFile : public IuFile
繼承 CuFile 的介面 IuFile
2010年1月17日 星期日
CuTestUnit - Easy way to Unit Test.
// Easy way to Unit Test.
// CuTestUnit.php
class CuTestUnit
{
var $debug;
function __construct()
{
$this->debug = new CuDebugger;
}
function CuTestUnit()
{
$this->__construct();
}
function assertTrue($bool, $key = null )
{
if( !$bool || $bool != true)
$result = "<font color = '#ff0000'>FALSE</font>";
else
$result = "<font color = '#0000ff'>OK</font>";
$this->debug->debug($result, $key);
}
function assertEquals($value1, $value2, $key = null)
{
$this->assertTrue($value1 == $value2, $key);
}
function GetHTML()
{
return $this->debug->GetHTML();
}
}
2010年1月16日 星期六
TuDeck - Card stack
// Card stack
// u_TDeck.pas
unit u_TDeck;
interface
uses
Windows, Classes, SysUtils,
StdCtrls,
ch_LogMessages,
u_TList,
u_TexasHoldConst;
const
CARD_LIMIT = (13 * 4); // 撲克牌總數 十三張 * 4種類
// 牌的位置
POSITION_POOL = 0; // 在牌堆裡
POSITION_HOLE = 1; // 玩家手牌
POSITION_FIELD = 2;// 桌上公牌
// 牌的類型
CARD_CATEGORY_SPADE = 0; // 黑桃
CARD_CATEGORY_HEARD = 1; // 紅心
CARD_CATEGORY_CLUB = 2; // 梅花
CARD_CATEGORY_DIAMOND = 3; // 方塊
CARD_CATEGORY_LIMIT = 4; //
type
//******************************************************************************
// 類別名稱:TCardData
// 功 能:每張牌的結構定義
//******************************************************************************
TCardData = class //TCardData 結構的定義
Category: word; // 種類
Index: word; // 數
ListIndex: word; // 表格位置
Position: word; // 位置
Player: integer; // 玩家
end;
//******************************************************************************
// 類別名稱:TuDeck
// 功 能:維護牌堆資料 提供 亂數取牌
//******************************************************************************
TuDeck = Class
private
m_aCardDataList: TuList; // 撲克牌陣列
m_DeckMessToFiles : TLogMessToFiles;
function GetRandomCardIndex: integer; // 找一張沒有被派發出來的牌
public
constructor Create;
destructor Destroy; override;
procedure Init; // 初始化
function GetRandomCard(Player, nPosition: integer): integer;
function GetIndexCard(nIndex,Player, nPosition:integer):integer;
function Items( nListIndex:integer ):TCardData;
function Index( nListIndex:integer ): word;
function Category( nListIndex:integer ): word;
function Position( nListIndex:integer ): word;
function Player( nListIndex:integer ): integer;
end;
function compareByPoker(Item1 : Pointer; Item2 : Pointer) : Integer;
implementation
constructor TuDeck.Create;
var
i: integer;
TmpCardData: TCardData;
begin
m_DeckMessToFiles := TLogMessToFiles.Create('DeckMessage.txt');
m_aCardDataList := TuList.Create();
for i := 0 to CARD_LIMIT - 1 do begin
TmpCardData := TCardData.Create();
m_aCardDataList.Add(TmpCardData);
end;
Init();
end;
destructor TuDeck.Destroy;
begin
m_aCardDataList.Free;
m_DeckMessToFiles.Free;
end;
//******************************************************************************
// 函式名稱:Init
// 功 能:初始化撲克牌陣列 並洗牌(重設亂數種子)
//******************************************************************************
procedure TuDeck.Init();
var
TmpCategory: integer;
TmpIndex: integer;
CardIndex: integer;
TmpCardData : TCardData;
begin
// 每一把要重新洗牌 重設亂數種子
Randomize;
CardIndex := 0;
for TmpCategory := 0 to CARD_CATEGORY_LIMIT - 1 do begin
for TmpIndex := 1 to CARD_INDEX_LIMIT do begin
TmpCardData := m_aCardDataList.GetItems(CardIndex);
TmpCardData.Category := TmpCategory;
TmpCardData.Index := TmpIndex;
TmpCardData.ListIndex := CardIndex;
TmpCardData.Position := POSITION_POOL;
TmpCardData.Player := PLAYER_NIL;
Inc(CardIndex);
end;
end;
end;
//******************************************************************************
// 函式名稱:GetIndexCard
// 功 能:直接取出 nIndex 指定的牌
//******************************************************************************
function TuDeck.GetIndexCard(nIndex,Player, nPosition:integer):integer;
var
TmpCardData : TCardData;
begin
TmpCardData := m_aCardDataList.GetItems(nIndex);
TmpCardData.Position := nPosition;
TmpCardData.Player := Player;
Result := nIndex;
end;
//******************************************************************************
// 函式名稱:GetRandomCard
// 功 能:亂數取牌
//******************************************************************************
function TuDeck.GetRandomCard(Player, nPosition: integer): integer;
var
nIndex: integer;
TmpCardData : TCardData;
begin
nIndex := GetRandomCardIndex();
TmpCardData := m_aCardDataList.GetItems(nIndex);
TmpCardData.Position := nPosition;
TmpCardData.Player := Player;
Result := nIndex;
end;
//******************************************************************************
// 函式名稱:GetRandomCardIndex
// 功 能:隨機取得 CardList 的參數
//******************************************************************************
function TuDeck.GetRandomCardIndex: integer;
var
TmpIndex, nIndex: integer;
nTmpNext : Integer;
nTmpPrev : Integer;
nRandom2 : Integer;
TmpCardData : TCardData;
begin
nIndex := Random(CARD_LIMIT);
// 如果 還沒發出去就直接發
TmpCardData := m_aCardDataList.GetItems(nIndex);
if TmpCardData.Position = POSITION_POOL then
begin
Result := nIndex;
exit;
end;
if nIndex = CARD_LIMIT - 1 then begin
nIndex := 0;
end;
(* 順序搜尋 *)
nTmpNext := -1;
for TmpIndex := nIndex to CARD_LIMIT - 1 do begin
TmpCardData := m_aCardDataList.GetItems(TmpIndex);
if TmpCardData.Position = POSITION_POOL then
begin
nTmpNext := TmpIndex;
break;
end;
end;
if nIndex = 0 then begin
nIndex := CARD_LIMIT - 1;
end;
nTmpPrev := -1;
for TmpIndex := nIndex downto 0 do begin
TmpCardData := m_aCardDataList.GetItems(TmpIndex);
if TmpCardData.Position = POSITION_POOL then begin
nTmpPrev := TmpIndex;
break;
end;
end;
// 當所有牌都發完時 才會兩個都是負的
// 如果發到都沒有牌 代表程式有問題
if (nTmpNext = -1) And (nTmpPrev = -1) then begin
m_DeckMessToFiles.m_WriteTXTOne(
Format ('nIndex %d nTmpNext %d nTmpPrev %d ',[nIndex, nTmpNext, nTmpPrev]), 1);
end;
if nTmpNext = -1 then begin
Result := nTmpPrev;
exit;
end;
if nTmpPrev = -1 then begin
Result := nTmpNext;
exit;
end;
nRandom2 := Random(CARD_LIMIT) mod 2;
if nRandom2 = 1 then begin
Result := nTmpNext;
end else begin
Result := nTmpPrev;
end;
end;
function TuDeck.Index( nListIndex:integer ): word;
begin
Result := TCardData(m_aCardDataList.GetItems(nListIndex)).Index;
end;
function TuDeck.Category( nListIndex:integer ): word;
begin
Result := TCardData(m_aCardDataList.GetItems(nListIndex)).Category;
end;
function TuDeck.Player( nListIndex:integer ): integer;
begin
Result := TCardData(m_aCardDataList.GetItems(nListIndex)).Player;
end;
function TuDeck.Position( nListIndex:integer ): word;
begin
Result := TCardData(m_aCardDataList.GetItems(nListIndex)).Position;
end;
function TuDeck.Items( nListIndex:integer ): TCardData;
begin
Result := m_aCardDataList.GetItems(nListIndex);
end;
end.
function compareByPoker(Item1 : Pointer; Item2 : Pointer) : Integer;
var
CardData1, CardData2: TCardData;
begin
CardData1 := Item1;
CardData2 := Item2;
if CardData1.Index > CardData2.Index then
Result := 1
else if CardData1.Index = CardData2.Index then
Result := 0
else
Result := -1;
end;
compare是給TList使用的牌堆取牌器(52張牌)
用在發牌, 發麻將, 都還不錯.
當然啦,除非要用, 不然在小弟的強大墮性的驅使下, 不會花時間做任何的多型!
2010年1月15日 星期五
CuListCtrl - Encapsulates the functionality of a "list view control"
// Encapsulates the functionality of a "list view control"
m_ListCtrl.Create( WS_VISIBLE | WS_CHILD | LVS_REPORT | LVS_SHOWSELALWAYS , rt, hWnd, (UINT)&1);
// CuListCtrl.h
class CuListCtrl
{
private:
CuWnd m_ListCtrlWnd;
public:
CuListCtrl(void);
~CuListCtrl(void);
virtual BOOL Create( DWORD dwStyle, const RECT& rect,
HWND hParentWnd, UINT nID );
int InsertColumn( int nCol, const LVCOLUMN* pColumn );
int InsertColumn( int nCol, TCHAR * lpszColumnHeading,
int nFormat = LVCFMT_LEFT, int nWidth = -1,int nSubItem = -1 );
int InsertItem( const LVITEM* pItem );
int InsertItem( int nItem, TCHAR * lpszItem );
int InsertItem( int nItem, TCHAR * lpszItem, int nImage );
int InsertItem( UINT nMask, int nItem, TCHAR * lpszItem,
UINT nState, UINT nStateMask, int nImage, LPARAM lParam );
BOOL SetItemText( int nItem, int nSubItem, TCHAR * lpszText );
};
// CuListCtrl.cpp
CuListCtrl::CuListCtrl(void)
{
}
CuListCtrl::~CuListCtrl(void)
{
}
BOOL CuListCtrl::Create(
DWORD dwStyle,
const RECT& rect,
HWND hParentWnd,
UINT nID
)
{
return m_ListCtrlWnd.Create(WC_LISTVIEW , L"", dwStyle, rect, hParentWnd, nID);
}
int CuListCtrl::InsertColumn( int nCol, const LVCOLUMN* pColumn )
{
return ListView_InsertColumn(m_ListCtrlWnd.GetSafeHwnd() , nCol, pColumn) ;
}
int CuListCtrl::InsertColumn( int nCol, TCHAR *lpszColumnHeading,
int nFormat /* = LVCFMT_LEFT */, int nWidth /* = -1 */ ,int nSubItem /* = -1 */)
{
LV_COLUMN lvC = {0};
lvC.mask = LVCF_FMT | LVCF_TEXT ;
if( nWidth != -1 )
{
lvC.mask = lvC.mask | LVCF_WIDTH;
lvC.cx = nWidth;
}
if( nSubItem != -1 )
{
lvC.mask = lvC.mask | LVCF_SUBITEM;
lvC.iSubItem = nSubItem;
}
lvC.fmt = nFormat;
lvC.pszText = lpszColumnHeading;
return this->InsertColumn( nCol, &lvC);
}
int CuListCtrl::InsertItem( const LVITEM* pItem )
{
return ListView_InsertItem(m_ListCtrlWnd.GetSafeHwnd(), pItem);
}
int CuListCtrl::InsertItem( int nItem, TCHAR * lpszItem )
{
LVITEM lvI = {0};
lvI.mask = LVIF_TEXT ;
lvI.iItem = nItem;
lvI.pszText = lpszItem;
return this->InsertItem( &lvI);
}
int CuListCtrl::InsertItem( int nItem, TCHAR * lpszItem, int nImage )
{
LVITEM lvI = {0};
lvI.mask = LVIF_TEXT | LVIF_IMAGE ;
lvI.iItem = nItem;
lvI.pszText = lpszItem;
lvI.iImage = nImage;
return this->InsertItem( &lvI);
}
int CuListCtrl::InsertItem( UINT nMask, int nItem, TCHAR * lpszItem,
UINT nState, UINT nStateMask, int nImage, LPARAM lParam )
{
LVITEM lvI = {0};
lvI.mask = nMask;
lvI.iItem = nItem;
lvI.pszText = lpszItem;
lvI.state = nState;
lvI.stateMask = nStateMask;
lvI.iImage = nImage;
lvI.lParam = lParam;
return this->InsertItem( &lvI);
}
BOOL CuListCtrl::SetItemText( int nItem, int nSubItem, TCHAR * lpszText )
{
ListView_SetItemText( m_ListCtrlWnd.GetSafeHwnd(), nItem, nSubItem, lpszText)
return true;
}
這個是很無聊的封裝, 但在CE上作業時, 不開MFC下, 也只能包一包
2010年1月14日 星期四
CuDebugger - Display PHP value about Array , Class detail information.
// Display PHP value about Array , Class detail information.
$debug = new CuDebugger
$debug->debug($result, $key);
// CuDebugger.php
class CuDebugger {
var $m_Data;
var $m_DataIndex;
function CuDebugger() {
$this->m_Data = array();
$this->m_DataIndex = 0;
}
function debug($data, $key = null, $innerText = false)
{
$index = $this->m_DataIndex + 1;
$this->m_Data[$index . " " .$key] = $data;
$this->m_DataIndex = $index;
}
function innerText($data, $key = null)
{
$data = str_replace("<", "& lt;", $data);
$data = str_replace(">", "& gt;", $data);
$this->debug($data, $key);
}
function GetHTML(){
return $this->printArray($this->m_Data);
}
function printArray($var) {
$title_string = "";
$string_row = "";
$string_value = "";
$string = "";
foreach($var as $key => $value){
if( is_array($value) ) {
$string_value .= $this->printArray($value, false);
}
elseif(gettype($value) == 'object') {
$string_value .= "Object of class " . get_class($value) . " { ".serialize($value) . " } ";
}
elseif( $value ) {
$string_value .= "$value";
}
else {
$string_value .= "< BR >";
}
$string_row .= "<tr>\n<td><b>$key</b></td><td>$string_value</td></tr>\n";
$string_value = "";
}
if( $string_row ) {
$string = '<table border = "1">'.$string_row;
$string .= "</table>\n";
}
return $string;
}
}
2010年1月13日 星期三
CuEdit - provides the functionality of a Windows edit control.
// provides the functionality of a Windows edit control.
CuEdit gEdit;
gEdit.Create( WS_VISIBLE|WS_CHILD| WS_BORDER,
CuRect(0, 0, 40 * 2 , 14 * 2), hWnd, (UINT)1);
gEdit.SetWindowText(TEXT("HI Edit"));
String strText;
gEdit.GetWindowText(strText);
// CuEdit.h
class CuEdit
{
CuWnd m_EditWnd;
public:
CuEdit(void);
~CuEdit(void);
virtual BOOL Create( DWORD dwStyle, const RECT& rect,
HWND hParentWnd, UINT nID );
void SetWindowText( LPCTSTR lpszString );
void GetWindowText( String& rString ) const;
};
// CuEdit.cpp
CuEdit::CuEdit(void)
{
}
CuEdit::~CuEdit(void)
{
}
BOOL CuEdit::Create( DWORD dwStyle, const RECT& rect,
HWND hParentWnd, UINT nID )
{
return m_EditWnd.CreateEx(WS_EX_CLIENTEDGE, TEXT("EDIT"),
TEXT(""), dwStyle, rect, hParentWnd, nID);
}
void CuEdit::SetWindowText( LPCTSTR lpszString )
{
::SetWindowText( m_EditWnd.GetSafeHwnd(), lpszString );
}
void CuEdit::GetWindowText( String& rString ) const
{
int nLenght = ::GetWindowTextLength( m_EditWnd );
TCHAR *pszBuffer = new TCHAR[nLenght + 1];
::GetWindowText(m_EditWnd , pszBuffer, nLenght);
rString = pszBuffer;
delete [] pszBuffer;
}
沒打算繼承CuWnd! 看不到多型 繼承後也沒任何好處!
2010年1月12日 星期二
CuWnd - is distinct from a Windows window
// is distinct from a Windows window
//
class CuMainWnd : public CuWnd {};
//
CuWnd ListCtrlWnd;
ListCtrlWnd.Create(WC_LISTVIEW , TEXT(""), dwStyle, rect, hParentWnd, nID);
CuWnd EditWnd;
EditWnd.CreateEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT(""), dwStyle, rect, hParentWnd, nID);
// CuWnd.h
class CuWnd
{
private:
HWND m_hWnd;
private:
//////////////////////////////////////////////////////////////////////
// 函式名稱: WndProc
// 函式說明: Create時預設的訊息回圈 會將訊息派送到 OnMsg裡
//////////////////////////////////////////////////////////////////////
static LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
public:
// 建構 解構
CuWnd(void);
virtual ~CuWnd(void);
protected:
//////////////////////////////////////////////////////////////////////
// 函式名稱: OnMsg
// 函式說明: 繼承這個函式處理windows訊息
//////////////////////////////////////////////////////////////////////
virtual LRESULT OnMsg(MSG &msg);
public:
virtual BOOL Create( LPCTSTR lpszClassName, LPCTSTR lpszWindowName,
DWORD dwStyle, const CuRect &rect,
HWND hParentWnd = NULL, UINT nID = NULL );
virtual BOOL CreateEx( DWORD dwExStyle, LPCTSTR lpszClassName,
LPCTSTR lpszWindowName, DWORD dwStyle, const CuRect& rect,
HWND hParentWnd = NULL, UINT nID = NULL);
ATOM WndRegisterClassEx(LPCTSTR szWindowClass);
// inline 函式 實作碼在下方
HWND GetSafeHwnd( ) const;
BOOL ShowWindow(int nCmdShow);
BOOL UpdateWindow();
BOOL DestroyWindow();
operator HWND() const
{
return GetSafeHwnd();
}
public:
// 訊息處理函式
void OnDestroy();
};
inline HWND CuWnd::GetSafeHwnd() const
{ return (HWND)(this == NULL ? NULL : m_hWnd) ;}
inline BOOL CuWnd::ShowWindow(int nCmdShow)
{ return ::ShowWindow( m_hWnd, nCmdShow); }
inline BOOL CuWnd::UpdateWindow()
{ return ::UpdateWindow(m_hWnd); }
inline BOOL CuWnd::DestroyWindow()
{
BOOL bResult = ::DestroyWindow(m_hWnd);
m_hWnd = NULL;
return bResult;
}
// CuWnd.cpp
CuWnd::CuWnd(void)
:m_hWnd(NULL)
{
}
CuWnd::~CuWnd(void)
{
this->DestroyWindow();
}
//////////////////////////////////////////////////////////////////////
// 函式名稱: OnMsg
// 函式說明: 預設訊息處理
//////////////////////////////////////////////////////////////////////
LRESULT CuWnd::OnMsg(MSG &msg)
{
return 0;
}
void CuWnd::OnDestroy()
{
PostQuitMessage(0);
}
LRESULT CALLBACK CuWnd::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static MSG msg;
msg.hwnd = hWnd;
msg.message = message;
msg.wParam = wParam;
msg.lParam = lParam;
static CuWnd *pWnd = NULL;
if( message == WM_CREATE )
{
CREATESTRUCT *pct = (LPCREATESTRUCT)lParam;
::SetWindowLong( hWnd , GWL_USERDATA, (LONG)pct->lpCreateParams );
}
pWnd = (CuWnd *)::GetWindowLong(hWnd, GWL_USERDATA);
if( pWnd && pWnd->OnMsg(msg) )
return 0;
else
return ::DefWindowProc(hWnd, message, wParam, lParam);
}
BOOL CuWnd::Create( LPCTSTR lpszClassName, LPCTSTR lpszWindowName,
DWORD dwStyle, const CuRect &rect,
HWND hParentWnd /* = NULL */, UINT nID /* = NULL*/ )
{
m_hWnd = ::CreateWindow(lpszClassName, lpszWindowName, dwStyle,
rect.left, rect.top, rect.Width(), rect.Height(),
hParentWnd, (HMENU)nID, GetModuleHandle(NULL), (LPVOID) this);
Assert( m_hWnd != NULL, L"CreateWindow Error");
DWORD dwError = GetLastError();
return (BOOL) (m_hWnd == NULL ? NULL : m_hWnd);
}
BOOL CuWnd::CreateEx( DWORD dwExStyle, LPCTSTR lpszClassName,
LPCTSTR lpszWindowName, DWORD dwStyle, const CuRect& rect,
HWND hParentWnd /* = NULL */, UINT nID /* = NULL*/)
{
m_hWnd = ::CreateWindowEx( dwExStyle, lpszClassName,
lpszWindowName, dwStyle,
rect.left, rect.top, rect.Width(), rect.Height(),
hParentWnd, (HMENU)nID, GetModuleHandle(NULL), (LPVOID) this);
Assert( m_hWnd != NULL, L"CreateWindow Error");
DWORD dwError = GetLastError();
return (BOOL) (m_hWnd == NULL ? NULL : m_hWnd);
}
ATOM CuWnd::WndRegisterClassEx(LPCTSTR szWindowClass)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(NULL);
wc.hIcon = 0;
wc.hCursor = 0;
wc.hbrBackground = 0;
wc.lpszMenuName = 0;
wc.lpszClassName = szWindowClass;
return RegisterClass(&wc);
}
2010年1月11日 星期一
CCriticalSection - a critical section object.
// a critical section object.
CCriticalSection m_cs;
...
m_cs.Enter();
...
m_cs.Leave();
// CCriticalSection.h
class CCriticalSection
{
CRITICAL_SECTION m_CriticalSection;
public:
void Leave();
void Enter();
CCriticalSection();
virtual ~CCriticalSection();
};
// CCriticalSection.cpp
CCriticalSection::CCriticalSection()
{
::InitializeCriticalSection(&m_CriticalSection);
}
CCriticalSection::~CCriticalSection()
{
::DeleteCriticalSection(&m_CriticalSection);
}
void CCriticalSection::Enter()
{
::EnterCriticalSection(&m_CriticalSection);
}
void CCriticalSection::Leave()
{
::LeaveCriticalSection(&m_CriticalSection);
}
2010年1月10日 星期日
CuKeyStatusComposite - group of KeyStatus
// group of KeyStatus
CuKeyStatusComposite ksComposite;
for( int j = 0 ; j < arr.size() ; j++ )
{
CuKeyStatus *pks = new CuKeyStatus;
// ...
ksComposite.push_back(pks);
}
ksComposite.clear();
// CuKeyStatusComposite.h
class CuKeyStatusComposite :
public TuComposite<CuKeyStatus>
{
public:
CuKeyStatusComposite(void);
~CuKeyStatusComposite(void);
int GetEqualItemIndex( CuKeyStatus &KeyStatus);
};
// CuKeyStatusComposite.cpp
CuKeyStatusComposite::CuKeyStatusComposite(void)
{
}
CuKeyStatusComposite::~CuKeyStatusComposite(void)
{
this->clear();
}
int CuKeyStatusComposite::GetEqualItemIndex( CuKeyStatus &KeyStatus)
{
int nResult = -1;
_itor = _itsElement.begin();
while( _itor != _itsElement.end() )
{
if( KeyStatus == *(*_itor) )
{
nResult = _itor - _itsElement.begin();
break;
}
_itor++;
}
return nResult;
}
GetEqualItemIndex 只有這個專案需要, 沒有打算移到 TuComposite 內, 下次在遇到時, 在處理.
2010年1月9日 星期六
CReg - An encapsulation of the Windows registry key.
// An encapsulation of the Windows registry key.
CReg reg(HKEY_LOCAL_MACHINE, TEXT("Software\\AppName\\"));
string strPath = reg.ValueSZ( "KeyName" );
// CReg.h
class CReg
{
private:
HKEY m_hKey;
int m_Index;
LPBYTE m_lpbValue; // last value read, if any
public:
CReg();
~CReg();
BOOL Create(HKEY hkRoot, LPCTSTR pszKey) {
DWORD dwDisp;
return ERROR_SUCCESS==RegCreateKeyEx(hkRoot, pszKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &m_hKey, &dwDisp);
}
BOOL Open(HKEY hkRoot, LPCTSTR pszKey, REGSAM sam=KEY_READ) {
return ERROR_SUCCESS==RegOpenKeyEx(hkRoot, pszKey, 0, sam, &m_hKey);
}
CReg(HKEY hkRoot, LPCTSTR pszKey) {
m_hKey = NULL;
m_Index = 0;
m_lpbValue = NULL;
Open(hkRoot, pszKey);
}
void MyFree(LPBYTE m_lpbValue) {
delete [] m_lpbValue;
}
LPBYTE MyRgAlloc(int dwLen)
{
return new BYTE[dwLen];
}
void Reset() {
if(m_hKey) RegCloseKey(m_hKey);
MyFree(m_lpbValue);
m_hKey = NULL;
m_Index = 0;
m_lpbValue = NULL;
}
operator HKEY() { return m_hKey; }
BOOL IsOK(void) { return m_hKey!=NULL; }
BOOL EnumKey(LPTSTR psz, DWORD dwLen) {
if(!m_hKey) return FALSE;
return ERROR_SUCCESS==RegEnumKeyEx(m_hKey, m_Index++, psz, &dwLen, NULL, NULL, NULL, NULL);
}
BOOL EnumValue(LPTSTR pszName, DWORD dwLenName, LPTSTR pszValue, DWORD dwLenValue) {
DWORD dwType;
if(!m_hKey) return FALSE;
dwLenValue *= sizeof(TCHAR); // convert length in chars to bytes
return ERROR_SUCCESS==RegEnumValue(m_hKey, m_Index++, pszName, &dwLenName, NULL, &dwType, (LPBYTE)pszValue, &dwLenValue);
}
BOOL ValueSZ(LPCTSTR szName, LPTSTR szValue, DWORD dwLen)
{
if(!m_hKey) return FALSE;
dwLen *= sizeof(TCHAR); // convert length in chars to bytes
return ERROR_SUCCESS==RegQueryValueEx(m_hKey, szName, NULL, NULL, (LPBYTE)szValue, &dwLen);
}
DWORD ValueBinary(LPCTSTR szName, LPBYTE lpbValue, DWORD dwLen) {
if(!m_hKey) return FALSE;
DWORD dwLenWant = dwLen;
if(ERROR_SUCCESS==RegQueryValueEx(m_hKey, szName, NULL, NULL, lpbValue, &dwLen))
return dwLen;
else
return 0;
}
LPCTSTR ValueSZ(LPCTSTR szName)
{
if(!m_hKey) return TEXT("");
DWORD dwLen = 0;
if( (ERROR_SUCCESS != RegQueryValueEx(m_hKey, szName, NULL, NULL, NULL, &dwLen)) ||
(dwLen == 0) )
return TEXT("");
MyFree(m_lpbValue);
if( !(m_lpbValue = MyRgAlloc(dwLen)) ||
(ERROR_SUCCESS != RegQueryValueEx(m_hKey, szName, NULL, NULL, m_lpbValue, &dwLen)) )
return TEXT("");
return (LPTSTR)m_lpbValue;
}
LPBYTE ValueBinary(LPCTSTR szName) {
return (LPBYTE)ValueSZ(szName);
}
DWORD ValueDW(LPCTSTR szName, DWORD dwDefault=0) {
if(!m_hKey) return FALSE;
DWORD dwValue = dwDefault;
DWORD dwLen = sizeof(DWORD);
RegQueryValueEx(m_hKey, szName, NULL, NULL, (LPBYTE)&dwValue, &dwLen);
return dwValue;
}
LONG ValueDW2(LPCTSTR szName, DWORD &dwDefault) {
if(!m_hKey) return FALSE;
DWORD dwValue = dwDefault;
DWORD dwLen = sizeof(DWORD);
return RegQueryValueEx(m_hKey, szName, NULL, NULL, (LPBYTE)&dwValue, &dwLen);
}
BOOL SetSZ(LPCTSTR szName, LPCTSTR szValue, DWORD dwLen) {
if(!m_hKey) return FALSE;
return ERROR_SUCCESS==RegSetValueEx(m_hKey, szName, 0, REG_SZ, (LPBYTE)szValue, sizeof(TCHAR)*dwLen);
}
BOOL SetSZ(LPCTSTR szName, LPCTSTR szValue) {
return SetSZ(szName, szValue, 1+lstrlen(szValue));
}
BOOL SetDW(LPCTSTR szName, DWORD dwValue) {
if(!m_hKey) return FALSE;
return ERROR_SUCCESS==RegSetValueEx(m_hKey, szName, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
}
BOOL SetBinary(LPCTSTR szName, LPBYTE lpbValue, DWORD dwLen) {
if(!m_hKey) return FALSE;
return ERROR_SUCCESS==RegSetValueEx(m_hKey, szName, 0, REG_BINARY, lpbValue, dwLen);
}
BOOL SetMultiSZ(LPCTSTR szName, LPCTSTR lpszValue, DWORD dwLen) {
return ERROR_SUCCESS==RegSetValueEx(m_hKey, szName, 0, REG_MULTI_SZ, (LPBYTE)lpszValue, sizeof(TCHAR)*dwLen);
}
BOOL DeleteValue(LPCTSTR szName) {
if(!m_hKey) return FALSE;
return ERROR_SUCCESS==RegDeleteValue(m_hKey, szName);
}
BOOL DeleteKey(LPCTSTR szName) {
if(!m_hKey) return FALSE;
return ERROR_SUCCESS==RegDeleteKey(m_hKey, szName);
}
};
// CReg.cpp
CReg::CReg()
{
m_hKey = NULL;
m_Index = 0;
m_lpbValue = NULL;
}
CReg::~CReg()
{
if(m_hKey)
RegCloseKey(m_hKey);
MyFree(m_lpbValue);
}
2010年1月8日 星期五
CuRecord - Access Record
// Access Record
$record = new CuRecord($ado, $table_name, $key);
//
$record->SetField("field_name", $field_value );
$record->Save();
//
$record->Load("field_name", $field_value);
$value = $record->GetField("field_name");
//
$record->Load("field_name", $field_value);
$record->Destroy();
// CuRecord.php
class CuRecord {
var $ado;
var $table_name;
var $key_name;
var $key_value;
var $database_fields;
var $modified_fields;
function CuRecord($ado, $table_name, $key_name = "sn" , $key_value = "") {
$this->ado = &$ado;
$this->table_name = $table_name;
$this->key_name = $key_name;
$this->key_value = $this->_check_input($key_value);
$this->database_fields = array();
$this->modified_fields = array();
}
function SetField( $field, $value) {
if( is_numeric($field) )
return;
$this->database_fields[$field] = $value;
$this->modified_fields[$field] = true;
}
function GetField($field) {
return $this->database_fields[$field];
}
function Destroy() {
if( !$this->key_value )
return;
return $this->ado->sql("DELETE FROM $this->table_name WHERE $this->key_name = '$this->key_value'");
}
function Save()
{
if( $this->key_value )
{
$result = $this->_update();
}
else
{
$result = $this->_insert();
$this->_load_key_value();
}
return $this->key_value;
}
function Load($bargain_field, $bargain_value)
{
if(!($bargain_field && $bargain_value ))
{
$bargain_field = $this->key_name;
$bargain_value = $this->key_value;
}
if( !($bargain_field && $bargain_value ) )
return;
$value = $this->_check_input($bargain_value);
$stmt = "`$bargain_field` = '$value'";
$stmt = "SELECT * FROM $this->table_name WHERE $stmt";
$result = $this->ado->sql($stmt);
if( $result == "" )
return ;
$result_table = $this->ado->fetch_array();
$this->database_fields = $result_table[0];
if( sizeof($this->modified_fields) > 0 ) {
foreach( $this->modified_fields as $key => $value ) {
$this->modified_fields[$key] = false;
}
}
$this->key_value = $result_table[0][$this->key_name];
return $this->key_value;
}
function _load_key_value()
{
$stmt = "SELECT MAX($this->key_name) AS $this->key_name FROM `$this->table_name` WHERE ";
foreach( $this->database_fields as $key => $value ){
if( !is_numeric($key) && $value ){
if( $this->modified_fields[$key] == true ){
$value = $this->_check_input($value);
$stmt .= "`$key` = '$value' AND ";
}
}
}
$stmt = substr($stmt,0,strlen($stmt)-5);
$handle = $this->ado->sql($stmt);
$result_table = $this->ado->fetch_array();
$this->key_value = $result_table[0][$this->key_name];
return $result_rows;
}
function _insert() {
$stmt = "INSERT INTO `$this->table_name` ";
foreach ($this->database_fields as $key => $value) {
if( !is_numeric( $key )&& $value){
$key = $this->_check_input($key);
$key_stmt .= " `$key`,";
$value = $this->_check_input($value);
$value_stmt .= " '$value',";
}
}
$key_stmt = substr($key_stmt,0,strlen($key_stmt)-1);
$value_stmt = substr($value_stmt,0,strlen($value_stmt)-1);
$stmt .= " (" . $key_stmt . ") VALUES (" . $value_stmt . ")" ;
$handle = $this->ado->sql($stmt, "_insert");
return $handle . " " . $stmt;
}
function _update() {
$field_value = $this->key_value;
$field_name = $this->key_name;
$table_name = $this->table_name;
$stmt = "UPDATE `$table_name` SET ";
foreach ($this->database_fields as $key => $value) {
if( !is_numeric( $key ) ){
if( $this->modified_fields[$key] == true ) {
$value = $this->_check_input($value);
if( $value == "" ){
$stmt .= "`$key` = 'NULL', ";
}
else {
$stmt .= "`$key` = '$value', ";
}
}
}
}
$stmt = substr($stmt, 0, strlen($stmt) - 2);
$stmt .= " WHERE `$field_name` = '$field_value'";
$handle = $this->ado->sql($stmt);
return $handle . " " . $stmt;
}
function _check_input($value)
{
if($value == "")
return "";
if (get_magic_quotes_gpc())
{
$value = stripslashes($value);
}
if (!is_numeric($value))
{
$value = mysql_real_escape_string($value);
}
return $value;
}
}
2010年1月7日 星期四
CuSize - Similar to the Windows SIZE structure
// Similar to the Windows SIZE structure
// CuSize.h
class CuSize : public tagSIZE
{
public:
// Constructors
// construct an uninitialized size
CuSize() throw();
// create from two integers
CuSize(int initCX, int initCY) throw();
// create from another size
CuSize(SIZE initSize) throw();
// create from a point
CuSize(POINT initPt) throw();
// create from a DWORD: cx = LOWORD(dw) cy = HIWORD(dw)
CuSize(DWORD dwSize) throw();
// Operations
BOOL operator==(SIZE size) const throw();
BOOL operator!=(SIZE size) const throw();
void operator+=(SIZE size) throw();
void operator-=(SIZE size) throw();
void SetSize(int CX, int CY) throw();
// Operators returning CuSize values
CuSize operator+(SIZE size) const throw();
CuSize operator-(SIZE size) const throw();
CuSize operator-() const throw();
// Operators returning CuPoint values
CuPoint operator+(POINT point) const throw();
CuPoint operator-(POINT point) const throw();
// Operators returning CuRect values
CuRect operator+(const RECT* lpRect) const throw();
CuRect operator-(const RECT* lpRect) const throw();
};
inline CuSize::CuSize()
{ /* random filled */ }
inline CuSize::CuSize(int initCX, int initCY)
{ cx = initCX; cy = initCY; }
inline CuSize::CuSize(SIZE initSize)
{ *(SIZE*)this = initSize; }
inline CuSize::CuSize(POINT initPt)
{ *(POINT*)this = initPt; }
inline CuSize::CuSize(DWORD dwSize)
{
cx = (short)LOWORD(dwSize);
cy = (short)HIWORD(dwSize);
}
inline BOOL CuSize::operator==(SIZE size) const
{ return (cx == size.cx && cy == size.cy); }
inline BOOL CuSize::operator!=(SIZE size) const
{ return (cx != size.cx || cy != size.cy); }
inline void CuSize::operator+=(SIZE size)
{ cx += size.cx; cy += size.cy; }
inline void CuSize::operator-=(SIZE size)
{ cx -= size.cx; cy -= size.cy; }
inline void CuSize::SetSize(int CX, int CY)
{ cx = CX; cy = CY; }
inline CuSize CuSize::operator+(SIZE size) const
{ return CuSize(cx + size.cx, cy + size.cy); }
inline CuSize CuSize::operator-(SIZE size) const
{ return CuSize(cx - size.cx, cy - size.cy); }
inline CuSize CuSize::operator-() const
{ return CuSize(-cx, -cy); }
inline CuPoint CuSize::operator+(POINT point) const
{ return CuPoint(cx + point.x, cy + point.y); }
inline CuPoint CuSize::operator-(POINT point) const
{ return CuPoint(cx - point.x, cy - point.y); }
inline CuRect CuSize::operator+(const RECT* lpRect) const
{ return CuRect(lpRect) + *this; }
inline CuRect CuSize::operator-(const RECT* lpRect) const
{ return CuRect(lpRect) - *this; }
2010年1月6日 星期三
CuADO - connection to a MySQL Server
// connection to a MySQL Server
$this->ado = new CuADO;
$ado->Connect($host, $username, $password);
$ado->SelectDB($db);
// CuADO.php
class CuADO {
var $link;
var $query_handle;
function CuADO() {
}
function Connect($host, $username, $password)
{
$this->link = mysql_connect($host, $username, $password);
return $this->link;
}
function SelectDB($db)
{
return mysql_select_db($db, $this->link);
}
function sql($stmt, $debug_key = "")
{
$this->query_handle = mysql_query($stmt, $this->link) ;
return $this->query_handle;
}
function fetch_array() {
$query_handle = &$this->query_handle;
$i = 0;
while($result_rows[$i] = mysql_fetch_array( $query_handle ) ){
$i++;
}
return $result_rows;
}
}
2010年1月5日 星期二
TuComposite - Template of Composite pattern
// allows a group of objects to be treated in the same way as a single instance of an object.
//
TuComposite<CuMyObject> myComposite;
CuMyObject *pMyObject = &myComposite;
//
class CuMyCompositeObject : public TuComposite<CuMyObject>
{
...
};
// TuComposite.h
template <typename T>
class TuComposite : public T
{
protected:
vector<T*> _itsElement;
typename vector<T*>::iterator _itor;
public:
TuComposite(){};
virtual ~TuComposite(){};
void push_back(T *pElement){ _itsElement.push_back(pElement); }
void insert(int n, T *pElement){ _itsElement.insert(_itsElement.begin() + n, pElement); }
T* at(const int nIndex){ return _itsElement[nIndex]; }
void reserve( int _Count ){_itsElement.reserve(_Count); }
int size(){ return _itsElement.size(); }
void remove(T *pElement);
void clear();
};
template <typename T>
void TuComposite<T>::clear()
{
_itor = _itsElement.begin();
while( _itor != _itsElement.end() )
{
T* pElement = *_itor;
delete pElement;
_itor++;
}
_itsElement.clear();
}
template <typename T>
void TuComposite<T>::remove(T *pElement)
{
_itor = _itsElement.begin();
while( _itor != _itsElement.end() )
{
if( pElement == *_itor )
{
_itsElement.erase(_itor);
break;
}
_itor++;
}
}
TuList - General purpose container of a list of objects
// General purpose container of a list of objects
ObjList : TuList;
ObjList := TuList.Create();
ObjList.Add(MyObject);
MyObject := ObjList.GetItems(i);
ObjList.Free;
// u_TList.pas
unit u_TList;
interface
uses
Windows, Classes, SysUtils,
StdCtrls,
ch_LogMessages;
type
TuList = class
private
m_List : TList;
public
constructor Create();
destructor Destroy(); override;
procedure Clear();
function Count: Integer;
function Add( Item:Pointer ):Integer;
function GetItems(Index: Integer): Pointer;
procedure Sort(Compare: TListSortCompare);
procedure Delete(Index: Integer);
end;
implementation
{ TuList }
function TuList.Add(Item: Pointer): Integer;
begin
Result := m_List.Add(Item);
end;
procedure TuList.Clear;
begin
m_List.Clear;
end;
function TuList.Count: Integer;
begin
Result := m_List.Count;
end;
constructor TuList.Create;
begin
m_List := TList.Create;
end;
procedure TuList.Delete(Index: Integer);
begin
m_List.Delete(Index);
end;
destructor TuList.Destroy;
begin
m_List.Free;
inherited;
end;
function TuList.GetItems(Index: Integer): Pointer;
begin
if (Index < 0) or (Index >= m_List.Count ) then begin
Index := 0;
end;
Result := m_List.Items[Index];
end;
procedure TuList.Sort(Compare: TListSortCompare);
begin
m_List.Sort(Compare);
end;
end.
2010年1月4日 星期一
CuKeyStatus - a struct of the keyboard status.
// a struct of the keyboard status.
// override operator ==
CuKeyStatus ksFromLLKeyHook;
CuKeyStatus ksClientDefault;
Assert( ksFromLLKeyHook == ksClientDefault );
// CuKeyStatus.h
class CuKeyStatus
{
public:
BOOL m_bAlt;
BOOL m_bCtrl;
BOOL m_bShift;
DWORD m_dwScanCode;
DWORD m_dwVirtualKey;
CuKeyStatus()
:m_bAlt(FALSE)
,m_bCtrl(FALSE)
,m_bShift(FALSE)
,m_dwScanCode(0)
,m_dwVirtualKey(0)
{};
~CuKeyStatus(void){};
BOOL operator == (CuKeyStatus &KeyStatus);
};
inline BOOL CuKeyStatus::operator == (CuKeyStatus &KeyStatus)
{
return m_bAlt == KeyStatus.m_bAlt &&
m_bCtrl == KeyStatus.m_bCtrl &&
m_bShift == KeyStatus.m_bShift &&
m_dwScanCode == KeyStatus.m_dwScanCode &&
m_dwVirtualKey == KeyStatus.m_dwVirtualKey ;
}
2010年1月3日 星期日
CuMenu - An encapsulation of the Windows HMENU.
// An encapsulation of the Windows HMENU.
CuMenu MenuTray.LoadMenu(IDR_MENU_MYMENU);
CuMenu *pTrackMenu = MenuTray.GetSubMenu(0);
pTrackMenu->TrackPopupMenu(TPM_BOTTOMALIGN, pt.x, pt.y, this->GetSafeHwnd() );
MenuTray.DestroyMenu();
// CuMenu.h
class CuMenu
{
HMENU m_hMenu;
public:
CuMenu(void);
~CuMenu(void);
BOOL DestroyMenu();
BOOL LoadMenu( UINT nIDResource );
CuMenu* GetSubMenu( int nPos ) const;
BOOL Attach( HMENU hMenu );
BOOL TrackPopupMenu(
UINT nFlags,
int x,
int y,
HWND hWnd,
LPCRECT lpRect = 0
);
};
// CuMenu.cpp
CuMenu::CuMenu(void)
:m_hMenu(NULL)
{
}
CuMenu::~CuMenu(void)
{
DestroyMenu();
}
BOOL CuMenu::LoadMenu( UINT nIDResource )
{
m_hMenu = ::LoadMenu(::GetModuleHandle(NULL), MAKEINTRESOURCE(nIDResource));
return ( m_hMenu != NULL );
}
CuMenu* CuMenu::GetSubMenu( int nPos ) const
{
HMENU hMenu = ::GetSubMenu( m_hMenu, nPos );
static CuMenu SubMenu;
SubMenu.Attach(hMenu);
return &SubMenu;
}
BOOL CuMenu::Attach( HMENU hMenu )
{
m_hMenu = hMenu;
return ( m_hMenu != NULL );
}
BOOL CuMenu::TrackPopupMenu(
UINT nFlags,
int x,
int y,
HWND hWnd,
LPCRECT lpRect /*= 0*/
)
{
return ::TrackPopupMenu(m_hMenu, nFlags, x, y, 0, hWnd, lpRect);
}
BOOL CuMenu::DestroyMenu()
{
return ::DestroyMenu(m_hMenu);
}
2010年1月2日 星期六
CuKeyboard - Conversion LowLevelKeyHook to CuKeyStatus
// Conversion LowLevelKeyHook to CuKeyStatus
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
static CuKeyboard Keyboard;
Keyboard.FromLowLevelKeyHook(wParam, lParam);
CuKeyNameTextEx KeyNameTextEx(Keyboard.GetKeyStatus());
wstring strKeyboard = KeyNameTextEx;
return 0;
}
CuHook hook;
hook.Init(HookProc, WH_KEYBOARD_LL);
// CuKeyboard.h
class CuKeyboard
{
CuKeyStatus m_KeyStatus;
BOOL m_bScanCode[256];
public:
CuKeyboard(void);
~CuKeyboard(void);
void FromLowLevelKeyHook(WPARAM wParam, LPARAM lParam);
CuKeyStatus GetKeyStatus(){ return m_KeyStatus; }
private:
bool IsFunctionKey(DWORD dwScanCode);
};
// CuKeyboard.cpp
CuKeyboard::CuKeyboard(void)
{
memset((void*)m_bScanCode, 0, sizeof(m_bScanCode) );
}
CuKeyboard::~CuKeyboard(void)
{
}
void CuKeyboard::FromLowLevelKeyHook(WPARAM wParam, LPARAM lParam)
{
KBDLLHOOKSTRUCT *pKB = (KBDLLHOOKSTRUCT *)lParam;
//
BOOL bKeyDown = ( (wParam == WM_KEYDOWN) || (wParam == WM_SYSKEYDOWN) );
m_bScanCode[pKB->scanCode] = bKeyDown;
//
if( IsFunctionKey(pKB->scanCode) )
{
m_KeyStatus.m_bAlt = m_bScanCode[56];
m_KeyStatus.m_bCtrl = m_bScanCode[29];
m_KeyStatus.m_bShift = (m_bScanCode[42] || m_bScanCode[54]);
}
else
{
if( !bKeyDown )
m_KeyStatus.m_dwScanCode = 0;
else
m_KeyStatus.m_dwScanCode = pKB->scanCode;
}
}
bool CuKeyboard::IsFunctionKey(DWORD dwScanCode)
{
return ((dwScanCode == 56) || (dwScanCode == 29) || (dwScanCode == 42) || (dwScanCode == 54));
}
2010年1月1日 星期五
CuPoint - A 2-D point, similar to Windows POINT structure.
// CuPoint - A 2-D point, similar to Windows POINT structure.
class CuPoint : public tagPOINT
{
public:
// Constructors
// create an uninitialized point
CuPoint() throw();
// create from two integers
CuPoint(int initX, int initY) throw();
// create from another point
CuPoint(POINT initPt) throw();
// create from a size
CuPoint(SIZE initSize) throw();
// create from an LPARAM: x = LOWORD(dw) y = HIWORD(dw)
CuPoint(LPARAM dwPoint) throw();
// Operations
// translate the point
void Offset(int xOffset, int yOffset) throw();
void Offset(POINT point) throw();
void Offset(SIZE size) throw();
void SetPoint(int X, int Y) throw();
BOOL operator==(POINT point) const throw();
BOOL operator!=(POINT point) const throw();
void operator+=(SIZE size) throw();
void operator-=(SIZE size) throw();
void operator+=(POINT point) throw();
void operator-=(POINT point) throw();
// Operators returning CuPoint values
CuPoint operator+(SIZE size) const throw();
CuPoint operator-(SIZE size) const throw();
CuPoint operator-() const throw();
CuPoint operator+(POINT point) const throw();
// Operators returning CuSize values
CuSize operator-(POINT point) const throw();
// Operators returning CuRect values
CuRect operator+(const RECT* lpRect) const throw();
CuRect operator-(const RECT* lpRect) const throw();
};
inline CuPoint::CuPoint()
{ /* random filled */ }
inline CuPoint::CuPoint(int initX, int initY)
{ x = initX; y = initY; }
inline CuPoint::CuPoint(POINT initPt)
{ *(POINT*)this = initPt; }
inline CuPoint::CuPoint(SIZE initSize)
{ *(SIZE*)this = initSize; }
inline CuPoint::CuPoint(LPARAM dwPoint)
{
x = (short)LOWORD(dwPoint);
y = (short)HIWORD(dwPoint);
}
inline void CuPoint::Offset(int xOffset, int yOffset)
{ x += xOffset; y += yOffset; }
inline void CuPoint::Offset(POINT point)
{ x += point.x; y += point.y; }
inline void CuPoint::Offset(SIZE size)
{ x += size.cx; y += size.cy; }
inline void CuPoint::SetPoint(int X, int Y)
{ x = X; y = Y; }
inline BOOL CuPoint::operator==(POINT point) const
{ return (x == point.x && y == point.y); }
inline BOOL CuPoint::operator!=(POINT point) const
{ return (x != point.x || y != point.y); }
inline void CuPoint::operator+=(SIZE size)
{ x += size.cx; y += size.cy; }
inline void CuPoint::operator-=(SIZE size)
{ x -= size.cx; y -= size.cy; }
inline void CuPoint::operator+=(POINT point)
{ x += point.x; y += point.y; }
inline void CuPoint::operator-=(POINT point)
{ x -= point.x; y -= point.y; }
inline CuPoint CuPoint::operator+(SIZE size) const
{ return CuPoint(x + size.cx, y + size.cy); }
inline CuPoint CuPoint::operator-(SIZE size) const
{ return CuPoint(x - size.cx, y - size.cy); }
inline CuPoint CuPoint::operator-() const
{ return CuPoint(-x, -y); }
inline CuPoint CuPoint::operator+(POINT point) const
{ return CuPoint(x + point.x, y + point.y); }
inline CuSize CuPoint::operator-(POINT point) const
{ return CuSize(x - point.x, y - point.y); }
inline CuRect CuPoint::operator+(const RECT* lpRect) const
{ return CuRect(lpRect) + *this; }
inline CuRect CuPoint::operator-(const RECT* lpRect) const
{ return CuRect(lpRect) - *this; }
CuKeyNameTextEx - retrieves a string that represents the name of a composite key
// retrieves a string that represents the name of a composite key
CuKeyStatus KeyStatus;
....
CuKeyNameTextEx KeyNameTextEx(KeyStatus);
wstring strKeyText = KeyNameTextEx;
// Assert( strKeyText == TEXT("Alt+Ctrl+Shift+D"));
// Assert( strKeyText == TEXT("Alt+Ctrl+D"));
// Assert( strKeyText == TEXT("Ctrl+Shift+D"));
// CuKeyNameTextEx.h
class CuKeyNameTextEx
{
wstring m_strKeyText;
public:
CuKeyNameTextEx(void);
CuKeyNameTextEx(CuKeyStatus &KeyStatus);
~CuKeyNameTextEx(void);
void SetKeyStatus(CuKeyStatus &KeyStatus);
operator wstring() const
{
return m_strKeyText;
};
BOOL IsMustAdd(bool l, bool r);
private:
wstring ProcessFunctionKey(CuKeyStatus &KeyStatus);
};
// CuKeyNameTextEx.cpp
CuKeyNameTextEx::CuKeyNameTextEx(void)
{
}
CuKeyNameTextEx::~CuKeyNameTextEx(void)
{
}
CuKeyNameTextEx::CuKeyNameTextEx(CuKeyStatus &KeyStatus)
{
SetKeyStatus(KeyStatus);
}
void CuKeyNameTextEx::SetKeyStatus(CuKeyStatus &KeyStatus)
{
if( !KeyStatus.m_dwScanCode )
return;
wstring strResult;
strResult = ProcessFunctionKey(KeyStatus);
CuKeyNameText KeyName(KeyStatus.m_dwScanCode);
wstring strKeyText = KeyName;
wstring strAdd = TEXT("+");
if( !strKeyText.empty() && !strResult.empty() )
strResult += strAdd;
strResult += strKeyText;
m_strKeyText = strResult;
}
wstring CuKeyNameTextEx::ProcessFunctionKey(CuKeyStatus &KeyStatus)
{
wstring strResult;
wstring strAlt = TEXT("Alt");
wstring strCtrl = TEXT("Ctrl");
wstring strShift = TEXT("Shift");
wstring strAdd = TEXT("+");
if( KeyStatus.m_bAlt )
strResult += strAlt;
if( KeyStatus.m_bAlt && KeyStatus.m_bCtrl )
strResult += strAdd;
if( KeyStatus.m_bCtrl )
strResult += strCtrl;
if( KeyStatus.m_bShift && (KeyStatus.m_bAlt || KeyStatus.m_bCtrl) )
strResult += strAdd;
if( KeyStatus.m_bShift )
strResult += strShift;
return strResult;
}
訂閱:
意見 (Atom)