////////////////////////////////////////////////////////////////////////////
既存ライブラリの導入方法
以下は例
1.XXX.lib、XXX.hをソースファイルがあるローカルにコピー
2.必要なdllを実行ファイルのローカルにコピー
3.プロジェクトへインポート(既存の追加)
4.リンカへの追加
[プロジェクト]→[プロパティー]→[入力]→[追加の依存ファイル]の、デバッグ、リリースそれぞれに、
"XXX.lib"を追加
////////////////////////////////////////////////////////////////////////////
関数間での変数受け渡し(変更された値を引数として返す関数)
1char
int XXXXXX::retFunc(char* strRet)
{
sprintf(strRet, strFrom);
return 0;
}
int XXXXX::CallFunc()
{
/////////
char strRet[MAX_PATH]
memset(strRet,0,MAX_PATH); //初期化をすること
retFunc(strRet);
/////
}
2.CString
bool ::retFunc(CString& strRetString)
{
strRetString = "これで返ったCStringには値が代入できる";
return true;
}
int XXXXX::CallFunc()
{
/////////
CString strRet;
retFunc(strRet);
/////
}
3.Struct
int XXXXX::retFunc(StructA* retS)
{
retS->a = 12345;
return 0;
}
int XXXXX::CallFunc()
{
/////////
StructA retS;
fnReadINIFile(&retS);
/////
}
////////////////////////////////////////////////////////////////////////////
簡単なスレッド関数の定義法
グローバルで関数を(例えば新規ヘッダーファイルに)書いて、呼びたいcppファイルでインクルードする
/*XXXX.cpp*/
#include runThread.h
int XXXXX::CallFunc()
{
/////////
AfxBeginThread(fnRunningThread, this, THREAD_PRIORITY_NORMAL);
/////
}
int XXXXX::setFunc();
{
//ここに処理
}
//イベントハンドラを使って終了させる例
void XXXXX::OnBnClickedRunningStop()
{
//イベントハンドラでボタンが押されたらスレッドを終了
m_IsLoopFlag = false;
}
/* runThread.h */
//runThread.h
UINT fnRunningThread(LPVOID pParam)
{
XXXXX *pThis = ( XXXXX *)pParam;
//ポインタをXXXXXクラスへの変換
while(1){
//XXXXXクラスのオブジェクトを実行したいときは
//関数の呼び出し
pThis->setFunc();
//変数の利用
pThis->m_strVar = "AAA";
//イベントハンドラを使って終了させる例
if(!pThis->m_IsLoopFlag){
break;
}
}
return 0;
}
////////////////////////////////////////////////////////////////////////////
CallBack関数の定義の仕方
定義(ヘッダ先頭部に記述)
↓↓↓
static int CALLBACK CallbackProc( HWND hwnd, UINT uMsg, LPARAM lParam,
LPARAM lpData );
記述(cpp内)
↓↓↓
int CALLBACK CallbackProc( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM
lpData )
{
//記述
//ループさせてSendMessage()、TranslateMessage()で、メッセージハンドラの取得
}
////////////////////////////////////////////////////////////////////////////
クラスの定義
クラスウィザードからクラスをつくって、それを利用する場合は、以下のようにする
int XXXXX::CallFunc()
{
/////////
CTestCtrl ObjCTestCtrl; //オブジェクトを作る
//クラスのメンバ変数は、セッターゲッター関数をつくってPrivateにしたほうがよい。
//publicならObjCTestCtrl.m_Var=1;のようにして呼べる
//関数の呼び出し
int Var;
ObjCTestCtrl.fnGetVar(Var); //ここで、fnGetVar()は、CTestCtrlクラス内のm_Varをゲットする為の関数
}
////////////////////////////////////////////////////////////////////////////
INIファイルへの書き出し、INIファイルからの読み出し
書き出し、読み込みは文字列で扱われるので、数値を入れたいときは変換する必要がある
int XXXXX::fnWriteINIFileSaveFile(char strWrite[MAX_PATH])
{
bool bRet = WritePrivateProfileString("セクション",
"値1", strWrite, m_strINIFilePath);
return 0;
}
int XXXXX::fnReadINIFileSaveFile(char strRead[MAX_PATH])
{
bool bRet = GetPrivateProfileString("セクション", "値1", "読み込みに失敗したらこの文字列がセットされます",
strRead, MAX_PATH, m_strINIFilePath);
return 0;
}
////////////////////////////////////////////////////////////////////////////
プログラムを引数つきで実行する
デバック時はプロジェクトのプロパティーの引数欄に指定する
引数の取得は
CString strCmdLine;
strCmdLine = AfxGetApp()->m_lpCmdLine;
で取得する
////////////////////////////////////////////////////////////////////////////
ボタンコントロール
m_bButton.EnableWindow(0); //押せなくする
m_bButton.EnableWindow(1); //押せるようになる
////////////////////////////////////////////////////////////////////////////
コンボボックス
m_cbCommboBox.InsertString(0, "この文字が表示されます");
//index0番目に文字列をセット
intRetIndex = m_cbCommboBox.GetCurSel();
//選ばれているindex値を取得
m_cbCommboBox.SetCurSel(0)
//INDEX0にセットする
////////////////////////////////////////////////////////////////////////////
エディットボックス
m_edEditBox.SetWindowText("文字列がセットされます");
m_edEditBox.GetWindowText(tmp);
//CString tmp;
////////////////////////////////////////////////////////////////////////////
ディレクトリ内のファイル全削除(ごみ箱に移さず削除する)
bool XXXXX::DeleteAllFileFromFolder(CString strFolder,CString strExtension)
{
BOOL bContinue;
CFileFind cFind;
CString strFile;
//パスの最後に\がついていなかったらつける
if(strFolder.Right(1) != "\\") strFolder += "\\";
strFolder += strExtension;
//FindFileで検索開始
bContinue = cFind.FindFile(strFolder);
while(bContinue){
bContinue = cFind.FindNextFile(); //次のファイルがあるか
if(cFind.IsDirectory() == FALSE){
//ファイルがあるなら削除
strFile = cFind.GetFilePath();
DeleteFile(strFile);
}
}
return true;
}
int XXXXX::CallFunc()
{
/////////
//たとえば、JPGファイルを全削除(ただし、jpgファイルは削除されない)
DeleteAllFileFromFolder(strDelDirPath, "*.jpg");
//すべてのファイルを削除
DeleteAllFileFromFolder(strDelDirPath, "*.*");
/////
}
////////////////////////////////////////////////////////////////////////////
シリアルポートとの通信(送受信のみエラー処理なし)
キャリッジリターン"\r"に注意
実際に送る文字列には追加、受け取る文字列からは、削除する必要がある(ただし仕様にもよる)
//接続用構造体定義
struct PortFileInfo{
CString strFileName; // ファイル名
DWORD dwDesiredAccess; // アクセスモード
DWORD dwShareMode; // 共有モード
LPSECURITY_ATTRIBUTES lpSecurityAttributes; // セキュリティ記述子
DWORD dwCreationDisposition; // 作成方法
DWORD dwFlagsAndAttributes; // ファイル属性
HANDLE hTemplateFile; // テンプレートファイルのハンドル
};
//変数
HANDLE m_hComm; //シリアル接続用ハンドル
PortFileInfo m_fileInfo; //シリアル接続用PortFileInfo構造体
DCB m_dcb; //シリアル接続用DCB構造体
bool m_fPortOpen; //ポートが開いているかどうか
//Open Port
//戻り値 成功:0 失敗:1
//PortFileInfo fileInfo CreateFileに必要な値の構造体(serialportctrl.h内に定義)
//DCB dcb シリアルポートとの接続用構造体
int SerialPortCtrl::OpenSerialPort(PortFileInfo fileInfo, DCB dcb)
{
if(!m_fPortOpen){ //Portが開いていなければOpen
//メンバ変数m_fileInfoに、PortFileInfo構造体をセット
if( SetFileInfo(fileInfo) != 0) return 2;
// シリアルポートのオープン
m_hComm = CreateFile ( m_fileInfo.strFileName,
// シリアルポートの文字列
m_fileInfo.dwDesiredAccess,
// アクセスモード
m_fileInfo.dwShareMode,
// 共有モード 0:他のアプリケーションからのアクセス拒否
m_fileInfo.lpSecurityAttributes,
// セキュリティ属性
m_fileInfo.dwCreationDisposition,
// 作成フラグ
m_fileInfo.dwFlagsAndAttributes,
// 属性
m_fileInfo.hTemplateFile
); // テンプレートのハンドル
//ハンドルが取得できなかった
if (m_hComm == INVALID_HANDLE_VALUE) return 3;
//DCB構造体をセット
if( SetDcb(dcb) != 0) return 4;
//成功してOpenできた
m_fPortOpen = TRUE;
return 0;
} else {
//Portは既に開いている
return 1;
}
}
//ClosePort
int SerialPortCtrl::CloseSerialPort()
{
//Portがひらいているかどうか
if(!m_fPortOpen) return 0; //Portはすでに閉じている
//開いていれば閉じる
if( !CloseHandle (m_hComm)) return 1;
return 0;
}
//外部からPortFileInfo構造体(メンバ変数)をセットする
int SerialPortCtrl::SetFileInfo(PortFileInfo setFileInfo)
{
m_fileInfo.dwCreationDisposition = setFileInfo.dwCreationDisposition;
m_fileInfo.dwDesiredAccess = setFileInfo.dwDesiredAccess;
m_fileInfo.dwFlagsAndAttributes = setFileInfo.dwFlagsAndAttributes;
m_fileInfo.dwShareMode = setFileInfo.dwShareMode;
m_fileInfo.hTemplateFile = setFileInfo.hTemplateFile;
m_fileInfo.lpSecurityAttributes = setFileInfo.lpSecurityAttributes;
m_fileInfo.strFileName = setFileInfo.strFileName;
return 0;
}
//外部からDCB構造体(メンバ変数)をセットする
int SerialPortCtrl::SetDcb(DCB setDCB)
{
if (!GetCommState (m_hComm, &m_dcb)) return 1; // DCBを取得失敗
m_dcb.BaudRate = setDCB.BaudRate;
m_dcb.ByteSize = setDCB.ByteSize;
m_dcb.fParity = setDCB.fParity;
m_dcb.Parity = setDCB.Parity;
m_dcb.StopBits = setDCB.StopBits;
if( !SetCommState (m_hComm, &m_dcb) ) return 1;
/*
//将来的にすべての値をセットできたほうがよい
//値をセットする方法を考えること↓ではだめです。0を入れたいときにセットできないから
if(setDCB.BaudRate != 0) m_dcb.BaudRate = setDCB.BaudRate;
if(setDCB.ByteSize != 0) m_dcb.ByteSize = setDCB.ByteSize;
if(setDCB.DCBlength != 0) m_dcb.DCBlength = setDCB.DCBlength;
if(setDCB.EofChar != 0) m_dcb.EofChar = setDCB.EofChar;
if(setDCB.ErrorChar != 0) m_dcb.ErrorChar = setDCB.ErrorChar;
if(setDCB.EvtChar != 0) m_dcb.EvtChar = setDCB.EvtChar;
if(setDCB.fAbortOnError != 0) m_dcb.fAbortOnError = setDCB.fAbortOnError;
if(setDCB.fBinary != 0) m_dcb.fBinary = setDCB.fBinary;
if(setDCB.fDsrSensitivity != 0) m_dcb.fDsrSensitivity =
setDCB.fDsrSensitivity;
if(setDCB.fDtrControl != 0) m_dcb.fDtrControl = setDCB.fDtrControl;
if(setDCB.fDummy2 != 0) m_dcb.fDummy2 = setDCB.fDummy2;
if(setDCB.fErrorChar != 0) m_dcb.fErrorChar = setDCB.fErrorChar;
if(setDCB.fInX != 0) m_dcb.fInX = setDCB.fInX;
if(setDCB.fNull != 0) m_dcb.fNull = setDCB.fNull;
if(setDCB.fOutX != 0) m_dcb.fOutX = setDCB.fOutX;
if(setDCB.fOutxCtsFlow != 0) m_dcb.fOutxCtsFlow = setDCB.fOutxCtsFlow;
if(setDCB.fOutxDsrFlow != 0) m_dcb.fOutxDsrFlow = setDCB.fOutxDsrFlow;
if(setDCB.fParity != 0) m_dcb.fParity = setDCB.fParity;
if(setDCB.fRtsControl != 0) m_dcb.fRtsControl = setDCB.fRtsControl;
if(setDCB.fTXContinueOnXoff != 0) m_dcb.fTXContinueOnXoff = setDCB.fTXContinueOnXoff;
if(setDCB.Parity != 0) m_dcb.Parity = setDCB.Parity;
if(setDCB.StopBits != 0) m_dcb.StopBits = setDCB.StopBits;
//こいつはエラーが出る if(setDCB.wReserved != 0) m_dcb.wReserved
= setDCB.wReserved;
if(setDCB.wReserved1 != 0) m_dcb.wReserved1 = setDCB.wReserved1;
if(setDCB.XoffChar != 0) m_dcb.XoffChar = setDCB.XoffChar;
if(setDCB.XoffLim != 0) m_dcb.XoffLim = setDCB.XoffLim;
if(setDCB.XonChar != 0) m_dcb.XonChar = setDCB.XonChar;
if(setDCB.XonLim != 0) m_dcb.XonLim = setDCB.XonLim;
if( !SetCommState (m_hComm, &m_dcb) ) return 1;
*/
return 0;
}
//SendMessag To Port
//この関数を使う前に必ずOpenSerialPort()関数でPortをOpenすること
//また、処理が済んだら、ハンドルをクローズすること
int SerialPortCtrl::SendMssage(PortFileInfo fileInfo, DCB dcb, CString
strMsg)
{
int nRes; //エラーコード返却用
if(m_fPortOpen){
char pszBuf[256]; // データ書き込みバッファ
DWORD dwWritten; // ポートへ書き込んだバイト数
OVERLAPPED osWrite = {0};
DWORD dwRes;
//charへの取り込み
memset(pszBuf, 0, sizeof(pszBuf)); //バッファ初期化
sprintf(pszBuf, strMsg); //コピー
osWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
if(!WriteFile (m_hComm, pszBuf, strlen(pszBuf), &dwWritten,
&osWrite)){
if (GetLastError() != ERROR_IO_PENDING) {
// WriteFile failed, but isn't delayed. Report error
and abort.
nRes = 10;
}else{
// Write is pending.
dwRes = WaitForSingleObject(osWrite.hEvent, INFINITE);
}
switch(dwRes){
// OVERLAPPED structure's event has been signaled.
case WAIT_OBJECT_0:
if (!GetOverlappedResult(m_hComm, &osWrite,
&dwWritten, FALSE))
nRes = 11;
else
// Write operation completed successfully.
nRes = 0;
break;
default:
// An error has occurred in WaitForSingleObject.
// This usually indicates a problem with the
// OVERLAPPED structure's event handle.
nRes = 12;
break;
}
}else{
// WriteFile completed immediately.
nRes = 0;
}
}else{
//Portが開いていていない
nRes = 1;
}
return nRes;
}
//Get Message From Port
int SerialPortCtrl::GetMssage(char* strRcvMsg)
{
if(m_fPortOpen){
// データの受信
DWORD dwErrors; // エラー情報
COMSTAT ComStat; // デバイスの情報
DWORD dwCount = 0; // 受信データのバイト数
// char pszBuf[256]; // データ読み出しバッファ
DWORD dwRead; // ポートから読み出したバイト数
memset(strRcvMsg, 0, sizeof(strRcvMsg)); //バッファ初期化
while(1){
ClearCommError (m_hComm, &dwErrors, &ComStat);
dwCount = (DWORD) ComStat.cbInQue;
if(dwCount != 0) break;
}
BOOL fWaitingOnRead = FALSE;
OVERLAPPED osReader = {0};
// Create the overlapped event. Must be closed before exiting
// to avoid a handle leak.
osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osReader.hEvent == NULL){
// Error creating overlapped event; abort.
}
if (!fWaitingOnRead) {
// Issue read operation.
if (!ReadFile(m_hComm, strRcvMsg, dwCount, &dwRead,
&osReader)) {
if (GetLastError() != ERROR_IO_PENDING){
// read not delayed?
// Error in communications; report it.
}else{
fWaitingOnRead = TRUE;
}
} else {
// read completed immediately
//HandleASuccessfulRead(pszBuf, dwRead);
}
}
return 0;
} else {
//Portが開いていない
return 1;
}
}
//一応ステータスを監視する
BOOL SerialPortCtrl::fnGetPortStatus(void)
{
if(m_fPortOpen) return TRUE;
else return FALSE;
}
////////////////////////////////////////////////////////////////////////////
ログファイルの取り方
BOOL WriteLog::SetWriteLogMsg(CString strFilePath, CString strLogMsg)
{
//時間を追加
char chrTime[128];
_strtime(chrTime); // hh:mm:ss形式で時刻を文字列に格納
strLogMsg = chrTime + strLogMsg;
//ファイルへの書き出し
char szBuffer[256];
FILE* stream = fopen(strFilePath,"a+");
if( stream != 0){
fseek(stream, 0, SEEK_SET);
sprintf(szBuffer, "\n%s", strLogMsg); //書き出し
fprintf( stream, "%s", szBuffer); //書き出し
fclose(stream); //クローズ
}
return true;
}
////////////////////////////////////////////////////////////////////////////
DWORDBit処理
SetA_VpdwOutParam1 = NULL ;
DWORD pdwOutParam1 = NULL ;
DWORD pdwOutParam2 = NULL ;
fnNTn_ChCtrl(m_pdwOpenID, NTNC_CHCTRL_PRESET_CH_GET, NULL, NULL,
&SetA_VpdwOutParam1, &pdwOutParam2) ;
if (HIWORD(SetA_VpdwOutParam1) == TNMEDIA_TV )
fnNTn_ChCtrl(m_pdwOpenID, NTNC_CHCTRL_PRESET_CH_SET, MAKEWPARAM(LOWORD(SetA_VpdwOutParam1),TNMEDIA_VIN),
NULL, &pdwOutParam1, &pdwOutParam2) ;
else
fnNTn_ChCtrl(m_pdwOpenID, NTNC_CHCTRL_PRESET_CH_SET, MAKEWPARAM(LOWORD(SetA_VpdwOutParam1),
TNMEDIA_TV), NULL, &pdwOutParam1, &pdwOutParam2) ;
////////////////////////////////////////////////////////////////////////////
レジストリの操作
CString CFnregDlg::RegszScan(HKEY hRegKey, LPSTR lpHKEY, LPSTR lpHKEntryName)
{
long lResult;
HKEY hKey;
lResult = RegOpenKeyEx(hRegKey,lpHKEY,0,KEY_ALL_ACCESS,&hKey);
if (lResult == ERROR_SUCCESS){
// CString szName;
char szName[MAX_PATH] ; //レジストリ文字列格納用
ZeroMemory(szName, sizeof(szName));//バッファの領域を0で初期化
DWORD dwType = REG_SZ ;
DWORD dwCount = MAX_PATH ;
// lResult = RegQueryValueEx(hKey, lpHKEntryName,NULL, &dwType,
(LPBYTE)szName, &dwCount);
lResult = RegQueryValueEx(hKey, lpHKEntryName,NULL, &dwType,
(LPBYTE)(LPCTSTR)szName, &dwCount);
if(lResult == ERROR_SUCCESS){
RegCloseKey(hKey) ;
return szName;//CStringe返す
}else{
RegCloseKey(hKey) ;
return "FAILED_SCANREG";//CStringe返す
}
}else{
RegCloseKey(hKey) ;
return "FAILED_OPENREG";//CStringe返す
}
}
DWORD CFnregDlg::RegdwScan(HKEY hRegKey, LPSTR lpHKEY, LPSTR lpHKEntryName)
{
DWORD dwRetErorr = 100;//erorr判定用
long lResult;
HKEY hKey;
lResult = RegOpenKeyEx(hRegKey,lpHKEY,0,KEY_ALL_ACCESS,&hKey);
if (lResult == ERROR_SUCCESS){
DWORD dwDate;//レジストリ数値格納用
DWORD dwType;
DWORD dwCount = sizeof(dwDate);
lResult = RegQueryValueEx(hKey, lpHKEntryName,NULL, &dwType,
(LPBYTE)&dwDate,&dwCount);
if(lResult == ERROR_SUCCESS){
RegCloseKey(hKey) ;
return dwDate;//DWORDで返す
}else{
RegCloseKey(hKey) ;
return dwRetErorr;
}
}else{
RegCloseKey(hKey) ;
return dwRetErorr;
}
}
BOOL CFnregDlg::RegszSet(HKEY hRegKey, LPSTR lpHKEY, LPSTR lpHKEntryName,
CString szName)
{//エントリの値をCString szNameに変更
long lResult;
HKEY hKey;
lResult = RegCreateKeyEx(hRegKey,lpHKEY,0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hKey,NULL
);
if ( lResult == ERROR_SUCCESS ){
DWORD dwCount = _MAX_PATH ;
lResult = RegSetValueEx( hKey, lpHKEntryName, NULL, REG_SZ,
(LPBYTE)(LPCTSTR)szName,dwCount );
if(lResult == ERROR_SUCCESS){
RegCloseKey(hKey);
return TRUE;
}else{
RegCloseKey(hKey);
return FALSE;
}
}else{
RegCloseKey(hKey);
return FALSE;
}
}
BOOL CFnregDlg::RegdwSet(HKEY hRegKey, LPSTR lpHKEY, LPSTR lpHKEntryName,
DWORD dwType)
{//エントリの値を"DWORD dwType"に変更
long lResult;
HKEY hKey;
lResult = RegCreateKeyEx(hRegKey,lpHKEY,0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hKey,NULL
);
if (lResult == ERROR_SUCCESS){
DWORD dwCount = sizeof(dwType) ;
lResult = RegSetValueEx( hKey, lpHKEntryName, NULL, REG_DWORD,
(LPBYTE)&dwType,dwCount );
if(lResult == ERROR_SUCCESS){
RegCloseKey(hKey);
return TRUE;
}else{
RegCloseKey(hKey);
return FALSE;
}
}else{
RegCloseKey(hKey);
return FALSE;
}
}
///////////////////////////////////////////////////////
//バイナリの読み込み
(未完成)
void CRegEdit::ScanbynryReg(HKEY hRegKey, LPSTR lpHKEY, LPSTR lpHKEntryName,
, WORD dwBuff/*[64]*/ , DWORD dwLen)
{
//レジストリからの取得・WORD dwBuff[64]に一括して格納
long m_lErr;
HKEY m_hkHandle;
// ZeroMemory(dwBuff, sizeof(dwBuff));
DWORD dwType = REG_BINARY;
// キーのオープン
m_lErr = RegOpenKeyEx(hRegKey, lpHKEY, 0, KEY_ALL_ACCESS, &m_hkHandle);
if(m_lErr != ERROR_SUCCESS ){
}else{
// Valueの長さを取得
m_lErr = RegQueryValueEx(m_hkHandle, lpHKEntryName, 0, &dwType,
NULL, &dwLen);
if(m_lErr != ERROR_SUCCESS ){
RegCloseKey(m_hkHandle);
}
// Valueの取得
m_lErr = RegQueryValueEx(m_hkHandle, "LOPW", 0, &dwType,
(LPBYTE)&dwBuff, &dwLen);
if(m_lErr != ERROR_SUCCESS){
RegCloseKey(m_hkHandle);
}
// キーのクローズ
RegCloseKey(m_hkHandle);
}
}
///////////////////////////////////////////////////
exe
DWORD dwTest = RegdwScan(HKEY_CURRENT_USER,strPath, "ControlDebugTrace");
CString szTest = RegszScan(HKEY_CURRENT_USER,strPath,"testsz");
szTest += "\\ok";
BOOL nRes = RegszSet(HKEY_CURRENT_USER, strPath, "testsz", szTest);
nRes = RegdwSet(HKEY_CURRENT_USER, strPath, "ControlDebugTrace",
1);
////////////////////////////////////////////////////////////////////////////
時間の取得
SYSTEMTIME lpSysTime;//システム日時構造体
GetSystemTime(&lpSysTime);//システム日時の取得(ミリ秒まで)
FILETIME lpFileTime ;//ファイルタイム構造体
SystemTimeToFileTime(&lpSysTime, &lpFileTime);//ファイルタイムに変換
CTime ctTime = CTime( lpFileTime, -1 );//CTimeを構築
char szTimeBuffer[256];
sprintf(szTimeBuffer,"%d/%#02d/%#02d %#02d:%#02d:%#02d:%#03d",ctTime.GetYear(),ctTime.GetMonth(),ctTime.GetDay(),
ctTime.GetHour(),ctTime.GetMinute(),ctTime.GetSecond(),lpSysTime.wMilliseconds);