在使用Rich Edit 2.0 Control時,要在App::InitInstance()裡,產生Dialog物件之前呼叫AfxInitRichEdit2()。
這樣才能使得編譯出來的程式可以執行,不然會在.DoModal()的時候就會出現handle錯誤而結束。
SMTP Client - send mail
目前參照http://www.codeproject.com/KB/IP/CSmtp.aspx?fid=1525693&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26所做出來的client端程式可正常運行。
唯獨在附加檔案的部份,一開始測試是讀取8k資料並傳送之,但是用outlook卻都收不到郵件。
由此可推測,是否是單一個section大小過大導致SMTP server拒絕接收郵件資料。
後來根據sample裡面設定的section大小(5k)來傳送,則可正常收到郵件。
故此目前先暫時用5k的section大小來傳遞檔案,以後有空的時候在來研究一下RFC。
Ref:RFC5246、 RFC2487。
Mail Format:(以下每一段建立後皆立即送出,括弧內或是藍色文字為註解)
唯獨在附加檔案的部份,一開始測試是讀取8k資料並傳送之,但是用outlook卻都收不到郵件。
由此可推測,是否是單一個section大小過大導致SMTP server拒絕接收郵件資料。
後來根據sample裡面設定的section大小(5k)來傳送,則可正常收到郵件。
故此目前先暫時用5k的section大小來傳遞檔案,以後有空的時候在來研究一下RFC。
Ref:RFC5246、 RFC2487。
Mail Format:(以下每一段建立後皆立即送出,括弧內或是藍色文字為註解)
Mail From:<SP>UserName<MailAddress><CRLF>
RCPT To:<SP>UserName<MailAddress><CRLF>(包含副本跟密件副本的收件人)
DATA (以下為郵件本體)
Header Content Start
Date:<SP>day<SP>month<SP>year<SP>hour:min:sec<SP>zone<CRLF>
From:<SP>UserName<MailAddress><CRLF>
X-Mailer:<SP>X-Mailer<CRLF>
Reply-To:<SP>MailAddress<CRLF>
X-Priority:<SP>Priority<CRLF>
To:UserName<MailAddress>,UserName<MailAddress>,...<CRLF>
Cc:UserName<MailAddress>,UserName<MailAddress>,...<CRLF>
Bcc:UserName<MailAddress>,UserName<MailAddress>,...<CRLF>
Subject:<SP>Subject<CRLF>
MIME-Version:<SP>version<CRLF>
(無附加檔)
Content-type: text/plain; charset=US-ASCII<CRLF>
Content-Transfer-Encoding: 7bit<CRLF><CRLF>
(*有附加檔,BOUNDARY_TEXT自定,網路上範例都將內容寫的很長)
Content-Type: multipart/mixed; boundary="BOUNDARY_TEXT"<CRLF><CRLF>
--BOUNDARY_TEXT<CRLF>
Content-type: text/plain; charset=US-ASCII<CRLF>
Content-Transfer-Encoding: 7bit<CRLF><CRLF>
Header Content End
Message body<CRLF>(每一行資料後面都要有crlf,但測試只有lf也是可以的。這邊郵件內容長度無限制,最好是一次送出)
(加入附加檔內容)
--BOUNDARY_TEXT<CRLF>
Content-Type: application/x-msdownload; name="FileName.ext"<CRLF>
Content-Transfer-Encoding: base64<CRLF>
Content-Disposition: attachment; filename="FileName.ext"<CRLF><CRLF>
(由Base64加密過的檔案內容,每一送出的Section大小不可超過6k)
(重覆做*,到所有檔案傳完為止)
--BOUNDARY_TEXT--(附加檔結束)
<CRLF>.<CRLF> (郵件內容傳送完畢)
QUIT<CRLF> (離開)
_SplitPath
C:\abc\123.txt => Drive = C:, Path = \abc\, FileName = 123, Extension = .txt
C:\abc\123.12.txt => Drive = C:, Path = \abc\, FileName = 123.12, Extension = .txt
C:\abc\123.txt.12 => Drive = C:, Path = \abc\, FileName = 123.txt, Extension = .12
\\192.168.1.1\abc\123.txt => Drive = "", Path = \\192.168.1.1\abc\, FileName = 123, Extension = .txt
C:\abc\123.12.txt => Drive = C:, Path = \abc\, FileName = 123.12, Extension = .txt
C:\abc\123.txt.12 => Drive = C:, Path = \abc\, FileName = 123.txt, Extension = .12
\\192.168.1.1\abc\123.txt => Drive = "", Path = \\192.168.1.1\abc\, FileName = 123, Extension = .txt
[Win]Service存取網路磁碟
目前測試在要進行存取時,先呼叫LogonUser()
之後就可以用所輸入的使用者帳號來存取網路磁碟了。
存取完後需使用CloseHandle()來關閉Token並釋放記憶體即可。
dwLogonType設成 LOGON32_LOGON_INTERACTIVE或是LOGON32_LOGON_NEW_CREDENTIALS則都可以。
只是網路磁碟的路徑要使用UNC路徑才行,不然還是一樣會找不到路徑。
mapping過的路徑目前測試結果是service是一定讀不到檔案,原因則目前不明。
如有需讀取mapping路徑內之資料,請參考[Win]Mapping Disk的紀錄位置
PS.如有需要讓呼叫的執行檔也有同樣的權時,dwLogonType需設成LOGON32_LOGON_INTERACTIVE;dwLogonProvider則要設為LOGON32_PROVIDER_DEFAULT。
之後再使用 CreateProcessAsUser()來執行執行檔即可。需傳入的Token則為先前使用LogonUser()所取得的token。
之後就可以用所輸入的使用者帳號來存取網路磁碟了。
存取完後需使用CloseHandle()來關閉Token並釋放記憶體即可。
dwLogonType設成 LOGON32_LOGON_INTERACTIVE或是LOGON32_LOGON_NEW_CREDENTIALS則都可以。
只是網路磁碟的路徑要使用UNC路徑才行,不然還是一樣會找不到路徑。
mapping過的路徑目前測試結果是service是一定讀不到檔案,原因則目前不明。
如有需讀取mapping路徑內之資料,請參考[Win]Mapping Disk的紀錄位置
PS.如有需要讓呼叫的執行檔也有同樣的權時,dwLogonType需設成LOGON32_LOGON_INTERACTIVE;dwLogonProvider則要設為LOGON32_PROVIDER_DEFAULT。
之後再使用 CreateProcessAsUser()來執行執行檔即可。需傳入的Token則為先前使用LogonUser()所取得的token。
[Container] 存有pointer的vector使用iterator取內容
使用方式如下
vector<CObj*>::iterator iterEnd = cObj.end();
vector<CObj*>::iterator iter = --iterEnd;
string strData = (*iter)->GetData();
[Reg]登入後自動啟動程式
將需執行的程式之路徑寫到下列Registry Key底下即可
Current User:
\\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
Local Machine:
\\HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
一樣可以加入command line來使用。
KeyValue的Type為String,KeyValue名稱可自定
已知所支援之平台:
XP、Vista、Server2008
Current User:
\\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
Local Machine:
\\HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
一樣可以加入command line來使用。
KeyValue的Type為String,KeyValue名稱可自定
已知所支援之平台:
XP、Vista、Server2008
[Win]Mapping Disk的紀錄位置
XP、Server2008、Vista、Win7:
Key:HKEY_CURRENT_USER\Network
ValueType:String
ValueName:Remote Path
Key:HKEY_CURRENT_USER\Network
ValueType:String
ValueName:Remote Path
[Win]在SystemTray Icon上跳出Pop-up Menu
一開始先加入Menu的resource,然後輸入所要顯示的項目。
之後將對應的ID加入到MessageMap裡面去,並且也需要建立對應的操作行為。
這邊所需要用到的Function為ON_COMMAND()
例如:
Message Map
之後再宣告CMenu物件來使用。宣告位置在function或是header內都可以。
之後需要彈出menu時,僅需做下列步驟:
Maximum function
In Head file
In Cpp
不過目前跳出來的Pop-up menu在focus離開後並不會自行消失,且無法使用HotKey,所以這邊之後有時間再補上。
2009/12/08 - 註記
Pop-up menu不會消失的問題,只需在顯示pop-up menu之前多加個main form的SetForegroundWindow()就可以解決了。
之後將對應的ID加入到MessageMap裡面去,並且也需要建立對應的操作行為。
這邊所需要用到的Function為ON_COMMAND()
例如:
Message Map
BEGIN_MESSAGE_MAP(CMainDlg, CDialog)
ON_COMMAND(ID_TRAYMENU_MAXIMIZE, OnTraymenuMax)
ON_COMMAND(ID_TRAYMENU_MINIMIZE, OnTraymenuMin)
ON_COMMAND(ID_TRAYMENU_CLOSE, OnTraymenuClose)
ON_COMMAND(ID_TRAYMENU_SHOWBALLOON, &CMDXMainDlg::OnTraymenuShowballoon)
END_MESSAGE_MAP()
之後再宣告CMenu物件來使用。宣告位置在function或是header內都可以。
之後需要彈出menu時,僅需做下列步驟:
this->m_pRClkMenu->LoadMenu(nMenuID);
this->m_pRClkMenu->GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, rect.left, rect.top, this, &rect);
this->m_pRClkMenu->Detach(); //這行也會讓menu消失
Maximum function
In Head file
afx_msg void OnTraymenuMax();
In Cpp
void CMainDlg::OnTraymenuMax()
{
this->ShowMainForm();
}
不過目前跳出來的Pop-up menu在focus離開後並不會自行消失,且無法使用HotKey,所以這邊之後有時間再補上。
2009/12/08 - 註記
Pop-up menu不會消失的問題,只需在顯示pop-up menu之前多加個main form的SetForegroundWindow()就可以解決了。
[MFC]比較安全的殺Modeless Dialog方法
在結束dialog之前,先在PostNcDestroy()內下PostMessage()或是SendMessage給()Parent Dialog來將pointer設成NULL。
之後再刪除this,這樣也比較不會發生modeless dialog內的destructor動作沒做完前,因Parent Dialog刪除modeless dialog而造成不定時的crash事件。
PostNcDestroy可以在IDDProperties裡面設定就可用了
Sample code
PostNcDestory
OnPostMessage
message map
in header file
in cpp
之後再刪除this,這樣也比較不會發生modeless dialog內的destructor動作沒做完前,因Parent Dialog刪除modeless dialog而造成不定時的crash事件。
PostNcDestroy可以在IDDProperties裡面設定就可用了
Sample code
PostNcDestory
void CMDXBatchJobManagerDlg::PostNcDestroy()
{
// TODO: Add your specialized code here and/or call the base class
CDialog::PostNcDestroy();
::AfxGetMainWnd()->PostMessage(WM_MDLESSDLG_CLOSE);
//::AfxGetMainWnd()->SendMessage(WM_MDLESSDLG_CLOSE);
delete this;
}
OnPostMessage
LRESULT CMDXBatchJobManagerDlg::OnPostMessage(WPARAM wParam, LPARAM lParam)
{
m_pModelessDlg = NULL; //Set null. It will be delete by itself
return TRUE;
}
message map
in header file
#define WM_MDLESSDLG_CLOSE 10058 //Any unique value
in cpp
BEGIN_MESSAGE_MAP(CMDXBatchJobManagerDlg, CDialog)
ON_MESSAGE(WM_MDLESSDLG_CLOSE, PostNcDestroy)
END_MESSAGE_MAP()
Dialog隱藏後不在task tray顯示
從程式最小化至系統列的測試中發現即使程式最小化之後,還是會存在task tray內,這樣看起來是有點怪。因此需要在最小化時,另外去處理。
所需用到的Api為SetWindowLongPtr(MSDN上說明這樣在32與64平台間比較有相容性)
所需用到的Api為SetWindowLongPtr(MSDN上說明這樣在32與64平台間比較有相容性)
LONG_PTR SetWindowLongPtr(
HWND hWnd,
int nIndex,
LONG_PTR dwNewLong
);
以及GetWindowLongPtr參數部分可參考CreateWindowEX裡的dwExStyle。LONG_PTR GetWindowLongPtr(
HWND hWnd,
int nIndex
);
要不顯示於task tray的時候需用SetWindowLongPtr(hWnd, GWL_EXSTYLE,GetWindowLong(hWnd, GWL_EXSTYLE) & ~WS_EX_TOOLWINDOW);
如需還原時則可使用SetWindowLongPtr(hWnd, GWL_EXSTYLE,GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_TOOLWINDOW);
這邊所使用的參數WS_EX_TOOLWINDOW據MSDN的說法,可以讓ALT+TAB的時候也看不到程式,但測試的結果是失敗的,所以看來還需要其他方法才能達成吧。
(結果上面那段寫完之後,竟然成功的在ALT+TAB裡面看不到隱藏的程式,這可真是神奇阿XDD)
最後完成的code如下:LRESULT CMainDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
switch ( message )
{
case WM_USER: //NOTE:滑鼠移到上面就會送這個進來了
if ( lParam == WM_LBUTTONDBLCLK )
{
SetWindowLongPtr(hWnd, GWL_EXSTYLE,this->ShowWindow(SW_SHOW);
}else if ( lParam == WM_RBUTTONDOWN ) {
::AfxMessageBox("OnMessage_Right button");
}
break;
case WM_SYSCOMMAND: //NOTE:OnCancel會進來到這邊
if ( wParam == SC_MINIMIZE || wParam == SC_CLOSE)
{
if ( wParam == SC_CLOSE )
{
SetWindowLongPtr(hWnd, GWL_EXSTYLE, this->ShowWindow(SW_HIDE);
this->GotoSystemTray();
}
}
break;
}
return CDialog::WindowProc(message, wParam, lParam);
}
Reference:http://delphi.ktop.com.tw/board.php?cid=168&fid=912&tid=74287
程式最小化至系統工具列
所需要用到的API為Shell_NotifyIcon
如有需要針對滑鼠點擊System tray裡面的Icon反應的話,則需在uCallbackMessage給定回傳之訊息。
之後再於
Sample-縮到System Tray:
WinProc code:
Reference:http://blog.chinaunix.net/u2/67530/showart_603037.html
其所需傳入的結構為 NOTIFYICONDATABOOL Shell_NotifyIcon(
DWORD dwMessage,
PNOTIFYICONDATA lpdata
);
傳入的Message有NIM_ADD、NIM_MODIFY、NIM_DELETE、NIM_SETFOCUS、NIM_SETVERSION
typedef struct _NOTIFYICONDATAA{
DWORD cbSize;
HWND hWnd;
UINT uID;
UINT uFlags;
UINT uCallbackMessage;
HICON hIcon;
#if (NTDDI_VERSION < NTDDI_WIN2K)
TCHAR szTip[64];
#endif
#if (NTDDI_VERSION >= NTDDI_WIN2K)
TCHAR szTip[128];
DWORD dwState;
DWORD dwStateMask;
TCHAR szInfo[256];
union{
UINT uTimeout;
UINT uVersion; // Used with Shell_NotifyIcon flag NIM_SETVERSION.
} DUMMYUNIONNAME;
TCHAR szInfoTitle[64];
DWORD dwInfoFlags;
#endif
#if (NTDDI_VERSION >= NTDDI_WINXP)
GUID guidItem;
#endif
#if (NTDDI_VERSION >= NTDDI_VISTA)
HICON hBalloonIcon;
#endif
}
如有需要針對滑鼠點擊System tray裡面的Icon反應的話,則需在uCallbackMessage給定回傳之訊息。
之後再於
LRESULT CDialog::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
裡面去接收所需要的資訊並作相對應的動作即可Sample-縮到System Tray:
bool CMainDlg::GotoSystemTray()
{
NOTIFYICONDATA NotifyIconData;
NotifyIconData.cbSize = sizeof (NOTIFYICONDATA);
NotifyIconData.hWnd = this->m_hWnd;
NotifyIconData.uID = IDD_MAINDLG;
NotifyIconData.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
NotifyIconData.hIcon = hIcon;
strcpy(NotifyIconData.szTip, "This is tip!!");
NotifyIconData.dwState = NIS_SHAREDICON;
strcpy(NotifyIconData.szInfo, "This is Info!!");
strcpy(NotifyIconData.szInfoTitle,"This is Info title!!");
NotifyIconData.dwInfoFlags = NIIF_INFO;
NotifyIconData.uCallbackMessage = WM_USER;
if ( !::Shell_NotifyIcon(NIM_ADD, &NotifyIconData) )
{
CString cstrDis;
cstrDis.Format("Err = %d", ::GetLastError());
::AfxMessageBox(cstrDis);
return false;
}
return true;
}
WinProc code:
LRESULT CMainDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
switch ( message )
{
case WM_USER: //NOTE:滑鼠移到上面就會送這個進來了
if ( lParam == WM_LBUTTONDBLCLK )
{
::AfxMessageBox("OnMessage_Left button");
}else if ( lParam == WM_RBUTTONDOWN ) {
::AfxMessageBox("OnMessage_Right button");
}
break;
case WM_SYSCOMMAND: //NOTE:OnCancel會進來到這邊
if ( wParam == SC_MINIMIZE || wParam == SC_CLOSE)
{::AfxMessageBox("OnSystem bar");}
break;
}
return CDialog::WindowProc(message, wParam, lParam);
}
Reference:http://blog.chinaunix.net/u2/67530/showart_603037.html
Subscribe to:
Posts (Atom)
Build docker image from multiple build contexts
Build docker image from multiple build contexts ...
-
參考資料: Input Input Manager 測試手把 :PS Analog gamepad Script語言:C# Unity 版本:3.4 Unity提供了3種輸入裝置可以使用,鍵盤、滑鼠、以及遊戲手把。 ...
-
Build docker image from multiple build contexts ...