Win32 & .Net Q&A
CSDN 討論總結系列:
問《VC++技術內幕》第四版p217,關於執行緒和MFC
書上說,不允許線上程之間共享MFC物件(此原則不適用於直接從CObject派生的物件或者是簡單的類),那麼我想在一個執行緒中開啟一個txt檔案並向裡面寫資料可否這樣做:
FILE* pfile= fopen(g_strSavepath,"wt");
其中CString g_strSavepath;是一個全域性變數。
另外,書上p217第7行提到,主執行緒有一個視窗,這個視窗指的是什麼?傳遞視窗控制代碼和傳遞視窗指標又有什麼區別?執行緒中是否只能用API函式呢?
幫同學做一個程式,沒想到裡面用到了執行緒,只好臨時抱佛腳了,請多多指教。謝謝!
答:每個MFC執行緒類包含一個主視窗指標成員。如果線上程類的主訊息迴圈中發現這個指標指向的視窗已經被銷燬,那麼會退出主訊息迴圈——這也導致執行緒終止。
使用其它執行緒建立的CString目前是安全的——但是你最好不要這麼做,鬼知道微軟在以後的MFC版本中會不會修改它的實現使其依賴於所線上程。字元陣列是安全的,而且路徑長度是有上限的,所以你可以使用TCHAR tszPath[_MAX_PATH}這樣一個字元陣列來儲存資料。一些其它型別的類和型別也可以用來線上程之間傳遞資料,例如BSTR等等。
執行緒使用的函式沒有限制,但是可以使用的MFC物件有限制,通常只允許訪問本執行緒建立的。如果你檢查一下CWinThread的原始碼就會發現它建立了一個臨時的視窗物件來在本執行緒內繼承父執行緒的主視窗——這是預設的行為,除非你手動指定一個主視窗。這個臨時的視窗物件是使用父執行緒的主視窗控制代碼來建立的。
問:把控制元件嵌入到WEB中,瀏覽時出現“控制元件執行某些功能不安全”的對話方塊,請問這些問題是什麼樣的原因造成?如果是控制元件的原因,那麼請問控制元件中安全問題該在何處增強?會不會也有指令碼編輯的問題存在?請高手幫忙?
問:BHO中攔截了DISPID_BEFORENAVIGATE2,之後怎樣顯示自定義Band?怎麼向自己寫的 Explorer Bar傳遞引數過去?
答:手動顯示/隱藏瀏覽欄可以參考http://support.microsoft.com/support/kb/articles/Q255/9/20.ASP 。在BHO中可以通過列舉視窗,獲得每個視窗所線上程ID之後,向本執行緒的視窗傳送自定義訊息來完成。
問:VC類中,怎樣宣告一個事件?
答:C++ 託管擴充套件和C++/CLI支援事件。
// Managed C++ Extension
__delegate void ClickEventHandler(int, double);
__delegate void DblClickEventHandler(String*);
__gc class EventSource {
__event ClickEventHandler* OnClick;
__event DblClickEventHandler* OnDblClick;
// ...
};
// C++/CLI
delegate void ClickEventHandler( int, double );
delegate void DblClickEventHandler( String^ );
ref class EventSource
{
event ClickEventHandler^ OnClick;
event DblClickEventHandler^ OnDblClick;
// ...
};
// Managed C++ Extension
// 顯式地實現add、remove和raise ...
public __delegate void f(int);
public __gc struct E {
f* _E;
public:
E() { _E = 0; }
__event void add_E1(f* d) { _E += d; }
static void Go() {
E* pE = new E;
pE->E1 += new f(pE, &E::handler);
pE->E1(17);
pE->E1 -= new f(pE, &E::handler);
pE->E1(17);
}
private:
__event void raise_E1(int i) {
if (_E)
_E(i);
}
protected:
__event void remove_E1(f* d) {
_E -= d;
}
};
// C++/CLI
delegate void f( int );
public ref struct E {
private:
f^ _E; //是的,委託也是引用型別
public:
E()
{ // 注意0換成了nullptr!
_E = nullptr;
}
// C++/CLI中顯式事件宣告的語法集合
event f^ E1
{
public:
void add( f^ d )
{
_E += d;
}
protected:
void remove( f^ d )
{
_E -= d;
}
private:
void raise( int i )
{
if ( _E )
_E( i );
}
}
static void Go()
{
E^ pE = gcnew E;
pE->E1 += gcnew f( pE, &E::handler );
pE->E1( 17 );
pE->E1 -= gcnew f( pE, &E::handler );
pE->E1( 17 );
}
};
你也可以實現回撥函式、傳送WM_NOTIFY訊息或者實現自動化連線相關介面來完成類似的功能。
問:我的CPropertySheet中有幾個page,在page的EditBox中改變輸入,想把框的輸入傳給變數。在OnOK()的響應裡,呼叫UpdateData(TRUE);但是得到的變數值沒有相應改變,請問為什麼?是不是屬性頁不能用UpdateData()?那麼我該怎麼樣使變數的值等於框的輸入值?
答:可以呼叫CPropertySheet::PressButton(PSBTN_APPLYNOW);手動進行資料交換;注意要用DDX把page上的變數和控制元件關聯起來
問:請問如何實現WinRar中那種從列表空件中拖放檔案到Windows的視窗中的功能。就是從我自己的應用程式中向Windows的通過雙擊“我的電腦”產生的視窗中拖放檔案,我查了下資料,估計要用到COleDataSource和鉤子函式方面的東西,小弟以前沒搞過,大俠們幫幫忙,又原始碼更好!
答:你可以自己實現OLE Drag/Drop 介面,參考微軟知識庫文章Q152092 DRAGD95.EXE OLE Drag/Drop in Windows 95 Common Controls和
http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/programmersguide/shell_basics/shell_basics_programming/transferring/datascenarios.asp。
問:首先,我確信已經將一段html 複製到了剪貼簿中,然後欲用下面程式碼取得 HTml 程式碼:
IDataObject iData = Clipboard.GetDataObject();
this.txtbox1.Text = (String)iData.GetData(DataFormats.Html);
可是得到的HTML卻是下面的一段程式碼(文字的開端有很多不需要的資訊):
Version:1.0
StartHTML:000000264
EndHTML:000000659
StartFragment:000000431
EndFragment:000000623
StartSelection:000000431
EndSelection:000000590
SourceURL:file://D:/quzw/To press/灞傛鏁版嵁搴揬Web淇℃伅鎶藉彇/Application/WebExtract/bin/Debug/Untitled.htm
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<BODY><!--StartFragment--><TABLE>
<TBODY>
<TR>
<TD width="95%"><B><A href="http://www.computer.org/">IEEE Computer
Society</A></B><BR><SPAN>Last updated 3 December From IEEE Annals</SPAN></TD></TR></TBODY></TABLE><!--EndFragment--></BODY>
</HTML>
而我想要得到的程式碼卻應該是:
<TR>
<TD width="95%"><B><A href="http://www.computer.org/">IEEE Computer
Society</A></B><BR><SPAN>Last updated 3 December From IEEE Annals</SPAN></TD>
</TR>
請問我該如何做???
答:
StartHTML:000000264
EndHTML:000000659
StartFragment:000000431
EndFragment:000000623
StartSelection:000000431
EndSelection:000000590
這些數值就是剪貼簿資料中對應的文字所在的範圍,以字元為單位
問:請問如何在資源管理器的右鍵選單中新增我自己的選單,以及如何寫我的選單響應命令,謝謝。另外如果可以知道使用者資源管理器右鍵選單“複製”到底是複製的那些東西(檔名or資料夾名)也可以(這樣我就不必去新增自己的選單了)
答:參考http://www.codeproject.com/shell/copypathext.asp
問:兩個webbrowser控制元件能共同一個session嗎?
答:同一程序的webbrowser控制元件共享一個session。例外:
程序手動傳送不合法的資料到IIS可能造成session丟失。
同時使用SSL和某些路由器,例如 Cisco Local Director,可能造成session丟失
問:WM的標準訊息是子類一直流到父類,遇到如WM_PAINT等訊息處理完就結束,其他就一層層向父類流,然後處理。
那麼WM_COMMAND訊息呢?這種訊息比較怪,子類收到後還會通知擁有者,比如按一個按鈕,按鈕的擁有者也會收到訊息,那麼他們怎麼處理呢?怎麼流呢?WM的標準訊息的處理我模擬出來了,型別機制也模擬出來了。但是WM_COMMAND和WM_NOTIFY訊息怎麼處理呢?大家說說自己的看法和理解,能有類似程式碼那是更好。
答:可以去看http://msdn.microsoft.com/library/en-us/vclib/html/_mfcnotes_tn021.asp
問:我以前已經有了一個C/s的系統,現在又開發了一個B/s的系統,也就是同一業務系統的兩部分。我現在想通過開發一個com,直接通過網頁上點選,來提取人員ID,然後在C/S程式中馬上調出人員資訊顯示,怎麼實現,大家給點思路?不知道大家用過eph沒有,他的聊天室搜尋中就是這麼幹得,點選後面的按鈕就把聊天室新增軟體中了。分不夠再加
答:有兩種方法
一種方法是實現自定義協議,通過解析URL來進行操作
另一種方法是實現IDocHostUIHandler,瀏覽器控制元件中的指令碼通過訪問window.external來訪問宿主程式。參考http://www.euromind.com/iedelphi/embeddedwb/ongetexternal.htm和http://www.euromind.com/iedelphi/app/pluggableprotocol.htm。
問:安裝了創天簡體中文企業版,下載了visual studio sp5中文版,在安裝時卻說語言版本不對,鬱悶啊~怎樣才能升級呢?
答:VC沒有官方中文版,打SP需要用英文版本的。
問:為什麼整型常量可以作為switch結構的case的值,而把變數強制轉換成常量就不行呢?
答:switch case不是if goto,編譯時可能要根據選項優化的。例如,某些編譯器可能優化等間隔的連續switch(例如0,1,2,3)到一個跳轉表。
問:如何用程式在IE中的收藏夾中新增一項?
答:你可以直接用SHGetSpecialFolderPath得到收藏夾的位置,然後在裡面用IShellLink建立url快捷方式。建立之後用SHChangeNotify通知其他程式。
問:如何攔截IE頁面浮動廣告?
答:可以列舉所有浮動的網頁元素(style.position="absolute")並且隱藏它們;但是最好在隱藏時通知使用者,因為並非全部的浮動元素都是廣告。
問:怎樣在一個FormView上面實現類似VC的IDE中WorkSpace那樣的標籤頁?
答:可以參考http://msdn.microsoft.com/msdnmag/issues/02/10/cqa/default.aspx、http://www.codeproject.com/docview/cpropertyview.asp和http://www.codeproject.com/docview/mditab.asp
問:如何讓CDHtmlDialog有滾動條??? 原來我是用CwebBrowser的,為了去掉它的邊框,我就用了CDHtmlDialog,但這個又沒有滾動條??怎麼能讓它又滾動條呢?謝謝
答:預設情況下CDHtmlDialog初始化的時候會取消滾動條void CDHtmlDialog::Initialize()
{
SetHostFlags(DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_SCROLL_NO);
在oninitdialog中之前呼叫SetHostFlags重新設定一下就好了。對話方塊面積大於網頁的時候想去掉滾動條的話,在DocumentComplete的時候設定body.scroll=auto。
問:怎樣模擬按下CTRL+ALT+DELETE?
答:可以參考http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/how_to_lock_the_workstation.asp
問:我用cfiledialog經過設定引數後多選檔案最多可以達到4750個
以後隨便增加多少記憶體都不能增加了!請問有沒有除了自己重新寫類的方法實現選取任意多個檔案?
答:參考我的文章http://blog.joycode.com/jiangsheng/archive/2004/11/22/39413.aspx
問:請問同一個專案裡可否同時存在託管程式碼和非託管程式碼 ?用巨集語句來告訴編譯器哪一段為託管 哪一段為非託管。
答:參考我的文章http://blog.joycode.com/jiangsheng/archive/2004/12/15/41209.aspx
問:本來我的Activex呼叫javascript函式已經實現,但是後來我的網頁被作為框架嵌入其他的網頁後就無法再成功呼叫了。Activex總是試圖呼叫主框架下的javascript函式,因而總是報出方法名找不到的錯誤。
先得到script的IDispatch介面
void CMyActivexCtrl::OnSetClientSite()
{
IServiceProvider *isp, *isp2 = NULL;
pScript=NULL;
pHTMLDocument=NULL;
pWebBrowser=NULL;
if (m_pClientSite)
{
do{
HRESULT hr = S_OK;
hr = m_pClientSite->QueryInterface(IID_IServiceProvider, reinterpret_cast<void **>(&isp));
if (FAILED(hr))
{
m_pClientSite->Release();
m_pClientSite=NULL;
break ;
}
hr = isp->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, reinterpret_cast<void **>(&isp2));
if (FAILED(hr))
{
m_pClientSite->Release();
m_pClientSite=NULL;
break ;
}
hr = isp2->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, reinterpret_cast<void **>(&pWebBrowser));
if (FAILED(hr))
{
m_pClientSite->Release();
isp->Release();
m_pClientSite=NULL;
isp=NULL;
break ;
}
hr = pWebBrowser->get_Document((IDispatch**)&pHTMLDocument);
if(FAILED(hr))
{
m_pClientSite->Release();
pWebBrowser->Release();
isp->Release();
isp2->Release();
m_pClientSite=NULL;
pWebBrowser=NULL;
isp=NULL;
isp2=NULL;
break ;
}
hr=pHTMLDocument->get_Script(&pScript);
if(FAILED(hr))
{
m_pClientSite->Release();
pHTMLDocument->Release();
pWebBrowser->Release();
isp->Release();
isp2->Release();
pHTMLDocument=NULL;
m_pClientSite=NULL;
pWebBrowser=NULL;
isp=NULL;
isp2=NULL;
break ;
}
if(isp){
isp->Release();
isp=NULL;
}
if(isp2){
isp2->Release();
isp2=NULL;
}
}while(FALSE);
}else{
DestroyWindow();
}
COleControl::OnSetClientSite();
}
然後再呼叫
//向js傳送資訊
LRESULT CMyDoc::outputParam(CString fuctionName,const CArray<CString> ¶ms)
{
extern IDispatch *pScript;
if(pScript==NULL){
return -1;
}
CComBSTR bstrMember(fuctionName);
DISPID dispid;
HRESULT hr=pScript->GetIDsOfNames(IID_NULL,&bstrMember,1,LOCALE_SYSTEM_DEFAULT,&dispid);
if(FAILED(hr)){
#ifdef _DEBUG
switch(hr)
{
case E_OUTOFMEMORY:
MessageBox(NULL,"E_OUTOFMEMORY","outputParam Err",0);
break;
case DISP_E_UNKNOWNNAME:
MessageBox(NULL,"DISP_E_UNKNOWNNAME","outputParam Err",0);
break;
case DISP_E_UNKNOWNLCID:
MessageBox(NULL,"DISP_E_UNKNOWNLCID","outputParam Err",0);
break;
}
#endif
return -1;
}
DISPPARAMS dispparams;
memset(&dispparams, 0, sizeof dispparams);
int paramNum=params.GetCount();
VARIANT *pParams=new VARIANT[paramNum];
for( int i = 0; i<paramNum; i++)
{
CComBSTR bstr =params.GetAt(i); // back reading
bstr.CopyTo(&pParams[i].bstrVal);
pParams[i].vt = VT_BSTR;
}
dispparams.rgvarg = pParams;
dispparams.cNamedArgs = 0;
dispparams.cArgs=paramNum;
EXCEPINFO excepInfo;
memset(&excepInfo, 0, sizeof excepInfo);
CComVariant vaResult;
UINT nArgErr = (UINT)-1; // initialize to invalid arg
hr = pScript->Invoke(dispid,IID_NULL,0,DISPATCH_METHOD,&dispparams,&vaResult,&excepInfo,&nArgErr);
delete []dispparams.rgvarg;
return 1;
}
但是這種方法只可以得到主框架裡面的javascript指令碼,Activex所在的網頁是作為子框架嵌入的就無法呼叫成功了。
有沒有人知道怎麼做?通過什麼辦法可以讓Acticex呼叫js的時候只在包含Activex的框架網頁中找對應的javascript程式碼呢?
答:hr = isp->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, reinterpret_cast<void **>(&isp2));
這不明擺是要訪問頂層框架麼?
m_pClientSite的container就是HTMLDocument物件,Get一下Container就可以了
問:如何指定開啟一個GOOGLE網頁,自動填入“HELLO”,自動單擊搜尋按鈕?不要用模擬按鍵的方法
答:首先訪問HTMLDocument的all屬性獲得HTML元素集合
然後列舉找到需要的表單元素(通過比較tagName或者通過查詢IHTMLFormElement介面)
之後訪問表單元素的element獲得表單項元素集合
然後列舉找到需要的輸入域元素(通過比較tagName或者通過查詢IHTMLInputElement介面)
之後訪問輸入域元素的value屬性
問:安裝vc6.0英文版或漢化版最後都提示DCOM註冊失敗,部分安裝和全部安裝也一樣結果,不知是何原因?XPsp2,高手救命!!!!
問:為什麼我安裝Visual Studio 6.0 時總是出錯?
換了光碟,中英文版都試了,總是出現下面的錯誤提示:
Setup was unable to create a DCOM user account in order to register 'C:/programe Files/Microsoft Visual Studio/ Common /Tools /VS-Ent98 /Vanalyzr /valec.exe
請會的朋友幫幫忙`~
先謝謝了`
答:參考http://support.microsoft.com/kb/257413
問:基於微軟WebBrowser控制元件開發的簡易瀏覽器,在訪問基於cookie或者session認證的網站時,如果網頁尾本里面自己彈出一個新的ie視窗,此窗口裡面就無法得到使用者的認證資訊,需要重新登入一次。
問題:通過我的自己寫的瀏覽器認證通過後,如何將這些資訊也傳入到新彈出ie窗口裡面?
答:在新建視窗時,如果瀏覽器控制元件的宿主沒有處理NewWindow2事件或者NewWindow事件,那麼會新建一個新的IE程序中的視窗,由於Session不能跨程序存在,依賴於Session的程式可能出現問題。
關於如何處理NewWindow2事件,可以參考http://support.microsoft.com/kb/184876/
問:如何釋放用SHGetFileInfo得到的圖示資源?我用如下語句得到某種型別檔案的圖示,可以成功。但如果對很多檔案都進行這種操作,在window資源管理器中發現本程式的GDI物件不停的增長,當超過10000時,系統介面就花了。
SHGetFileInfo(WFD.cFileName,FILE_ATTRIBUTE_NORMAL,&fileInfoS,sizeof(fileInfoS),SHGFI_USEFILEATTRIBUTES|SHGFI_TYPENAME|SHGFI_ICON);
答:If SHGetFileInfo returns an icon handle in the hIcon member of the SHFILEINFO structure pointed to by psfi, you are responsible for freeing it with DestroyIcon when you no longer need it.
問:VC下面繪製不相交的連續線段的問題. 目的實現就是用滑鼠點選一系列的點,將各個點連成直線,但是不允許與已經存在的線相交.大概要怎麼做呢?
答:對已經存在的點進行某種方式的排序,然後以這種排的序列依次連線.
方法1
1 找任意一個和點集中任何兩點都不在一個直線上的點
2 以此點為極點,任一方向為極軸建立極座標系。
3 將點集按極座標的角度排序
4 按照此順序連線點集中的點
或者
方法2
找凸包
剩餘的點再次找凸包
迴圈直到所有的點都進入了凸包當中
顯然這些凸包是相互包含的,一個套一個,然後再開啟這個系列凸包就是了。所謂的開啟,就是從凸包上的任意一點,找到下一個凸包上的一個點,使得他們之間的連線和內部凸包無交點即可
這樣的結果是一個類似螺旋形狀的折線
為了說明問題,把處理方案規劃成為找多個凸包
實際上在具體操作當中,找凸包的同時就可以生成這個解的
一堆點如何找凸包?
先找出一個極值點,比如y分量最小的點當中x分量最小的點,它肯定是凸包上的一個點
然後從這裡開始找一個點,使得其他的點都在這個點和和起點的連線的同一側
記錄這個線段,然後再把找到的點作為新的起點,找下一個線段,一直到完成一個封閉的多邊形為止
參考http://search.csdn.net/Expert/topic/2483/2483852.xml?temp=.5336725
問:我在WinForm程式中做一個類於Outlook/Foxmail的郵件編輯傳送軟體.在Html Editor編輯功能中, 通過瀏覽插入本地圖片時,在郵件內容中只是記錄了一個圖片路徑, 這樣傳送出去的郵件,客戶不能看到圖片.
請問哪位大俠知道Outlook/Foxmail是如何將圖片做為郵件的一部分(不是在附件中)傳送出去的? 應該是MHTML功能吧? 如何實現上述功能呢? 請給出例子程式碼.
答:可以參考http://www.codeproject.com/vb/net/MhtBuilder.asp
問:怎麼看VC6是否安裝了sp5和sp6?
答:參考微軟知識庫文章 如何判斷是否安裝了 Visual Studio Service Pack http://support.microsoft.com/kb/194295
問:我想做一個Activex來監聽一個伺服器的埠,接受到伺服器指令後就呼叫頁面相應的JS函式,請問大家能不能這樣實現?Activex呼叫頁面JS函式該如何寫?
答:可以,ActiveX的容器是HTMLDocument物件,執行其ExecScript方法即可。
微軟知識庫文章Q172763 INFO: Accessing the Object Model from Within an ActiveX Control 描述瞭如何使用IOleClientSite來和IE這個控制元件容器互動。可以使用IOleClientSite::GetContainer得到網頁所在HTML文件物件的IOleContainer介面,然後再查詢其他介面,例如IHTMLDocument2來進行對DHTML物件模型的訪問。
IHTMLDocument2::scripts屬性表示HTML文件中所有指令碼物件。使用指令碼物件的IDispatch介面的::GetIDsOfNames方法可以"發現其中的函式和物件成員,使用IDispatch::Invoke可以訪問這些成員。也可以用IHTMLDocument2::ExecScript執行指令碼。
也可以在activex裡宣告事件,在腳本里編寫此事件的處理程式碼。
問:近一直在學習瀏覽器的開發。遇到一問題,找了幾天資料也沒能解決。希望大家給點支援和幫助,謝謝了!具體問題如下:
我以MDI模式和利用axwebBrowser組建做了一個瀏覽器,現在點選一個彈出式視窗的連線的時候會同時彈出兩個視窗,一個是我瀏覽器內的(正確),一個是IE瀏覽器的(多餘)。我現在想知道為什麼和怎麼做能遮蔽掉IE自動彈出來的這個視窗。
部分相關程式碼如下
private void Mdi_Load(object sender, System.EventArgs e)
{
Thread t = new Thread(new ThreadStart(GoGo));
t.Start();
webBrowser_V1 = (SHDocVw.WebBrowser_V1)this.axWebBrowser1.Application;
this.webBrowser_V1.NewWindow += new SHDocVw.DWebBrowserEvents_NewWindowEventHandler(webBrowser_V1_NewWindow);
}
private void webBrowser_V1_NewWindow(string URL, int Flags, string TargetFrameName, ref object PostData, string Headers, ref bool Processed)
{
Mdi form2 = new Mdi(URL);
form2.MdiParent = this.MdiParent;
form2.Show();
}
答:NewWindow2事件在建立新視窗之前都會被觸發(NewWindow事件是為了相容性而觸發的,在新的程式碼中不應該處理這個事件)
如果要停止預設的處理(在Internet Explorer中開啟新的視窗),需要設定Cancel指向的值為真
參考http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/webbrowser/reference/ifaces/dwebbrowserevents2/newwindow2.asp
對於private void webBrowser_V1_NewWindow(string URL, int Flags, string TargetFrameName, ref object PostData, string Headers, ref bool Processed)
這個宣告,設定Processed為真就可以了。
對於private void axWebBrowser1_NewWindow2(object sender, AxSHDocVw.DWebBrowserEvents2_NewWindow2Event e)這個宣告,需要設定e.cancel為真。
問:IE程式設計,取得當前滑鼠指向的表單域的值?
如果網頁中沒有子frame,則用下面的語句可以獲得,但是如果網頁中帶有frame,則我要獲取的frame不是主frame時,下面的語句就無效了
HTMLElement := HTMLDocument.elementFromPoint(p.X,p.Y);
有兩個問題不懂,
一、如何當到前前滑鼠指向的frame,並得到frame中的IHTMLDocument介面?
二、如何把p.X與p.Y轉換為相對於frame中的座標?
答:1 elementFromPoint獲得frame之後查詢IWebBrowser2介面
2 根據框架左上角的位置換算一下座標
參考資料
http://www.codeguru.com/Cpp/I-N/ieprogram/security/article.php/c4387
問:如何根據檔案的副檔名 得到作業系統中相應的圖示?
答:
private void button1_Click(object sender, System.EventArgs e)
{
this.Icon=ExtractIcon.GetIcon("D://111.txt",false);
}
using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Forms;
/// <summary>
/// Summary description for ExtractIcon.
/// </summary>
public class ExtractIcon
{
[DllImport("Shell32.dll")]
private static extern IntPtr SHGetFileInfo
(
string pszPath,
uint dwFileAttributes,
out SHFILEINFO psfi,
uint cbfileInfo,
SHGFI uFlags
);
[DllImport("comctl32.dll")]
private static extern int ImageList_GetImageCount(
IntPtr himl
);
[DllImport("comctl32.dll")]
private static extern IntPtr ImageList_GetIcon(
IntPtr himl,
int i,
uint flags
);
[StructLayout(LayoutKind.Sequential)]
private struct SHFILEINFO
{
public SHFILEINFO(bool b)
{
hIcon=IntPtr.Zero;iIcon=0;dwAttributes=0;szDisplayName="";szTypeName="";
}
public IntPtr hIcon;
public int iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.LPStr, SizeConst=260)]
public string szDisplayName;
[MarshalAs(UnmanagedType.LPStr, SizeConst=80)]
public string szTypeName;
};
private ExtractIcon()
{
}
private enum SHGFI
{
SHGFI_ICON = 0x000000100, // get icon
SHGFI_DISPLAYNAME = 0x000000200, // get display name
SHGFI_TYPENAME = 0x000000400, // get type name
SHGFI_ATTRIBUTES = 0x000000800, // get attributes
SHGFI_ICONLOCATION = 0x000001000, // get icon location
SHGFI_EXETYPE = 0x000002000, // return exe type
SHGFI_SYSICONINDEX = 0x000004000, // get system icon index
SHGFI_LINKOVERLAY = 0x000008000, // put a link overlay on icon
SHGFI_SELECTED = 0x000010000, // show icon in selected state
SHGFI_ATTR_SPECIFIED = 0x000020000, // get only specified attributes
SHGFI_LARGEICON = 0x000000000, // get large icon
SHGFI_SMALLICON = 0x000000001, // get small icon
SHGFI_OPENICON = 0x000000002, // get open icon
SHGFI_SHELLICONSIZE = 0x000000004, // get shell size icon
SHGFI_PIDL = 0x000000008, // pszPath is a pidl
SHGFI_USEFILEATTRIBUTES = 0x000000010 // use passed dwFileAttribute
}
private enum SHIL
{
SHIL_LARGE = 0, // normally 32x32
SHIL_SMALL = 1, // normally 16x16
SHIL_EXTRALARGE = 2,
SHIL_SYSSMALL = 3 // like SHIL_SMALL, but tracks system small icon metric correctly
}
/// <summary>
/// Get the associated Icon for a file or application, this method always returns
/// an icon. If the strPath is invalid or there is no idonc the default icon is returned
/// </summary>
/// <param name="strPath">full path to the file</param>
/// <param name="bSmall">if true, the 16x16 icon is returned otherwise the 32x32</param>
/// <returns></returns>
public static Icon GetIcon(string strPath, bool bSmall)
{
SHFILEINFO info = new SHFILEINFO(true);
int cbFileInfo = Marshal.SizeOf(info);
SHGFI flags;
if (bSmall)
flags = SHGFI.SHGFI_ICON|SHGFI.SHGFI_SMALLICON;
else
flags = SHGFI.SHGFI_ICON|SHGFI.SHGFI_SMALLICON|SHGFI.SHGFI_USEFILEATTRIBUTES;
SHGetFileInfo(strPath, 256, out info,(uint)cbFileInfo, flags);
return Icon.FromHandle(info.hIcon);
}
public static int GetIconIndex(string strPath, ImageList imgList)
{
SHFILEINFO info = new SHFILEINFO(true);
int cbFileInfo = Marshal.SizeOf(info);
SHGFI flags;
IntPtr hIcon;
flags = SHGFI.SHGFI_SYSICONINDEX|SHGFI.SHGFI_SMALLICON;
IntPtr ret = SHGetFileInfo("c://", 256, out info, (uint)cbFileInfo, flags);
int nbIcon = ImageList_GetImageCount(ret);
for (int i = 0; i < nbIcon; i++)
{
hIcon = ImageList_GetIcon(ret, i, 0);
imgList.Images.Add (Icon.FromHandle(hIcon));
}
return info.iIcon;
}
}
問:我有一個日期格式的CString值,我要賦給一個CTime的變數,請問用什麼方法轉換最好?
答:COleDateTime::ParseDateTime可以解析標準格式的時間,參考http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_MFC_COleDateTime.asp
但是對於不標準格式的時間,沒有現成的演算法。你需要自行設計解析函式,例如使用scanf。COleDateTime不一定可以轉CTime的,因為CTime的時間是從0:00:00 GMT, January 1, 1970至
03:14:07 January 19 2038,而COleDateTime是從 1 January 100開始到31 December 9999的。如果你確定時間可以轉換,那麼可以使用CTime的一個建構函式:
CTime( int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, int nDST = -1 );
其中引數的值可以呼叫COleDateTime的對應成員函式獲得。
問:用VB.net 編 天干地支 的最簡單方法 是怎麼編啊 !
答:可以用.Net 2.0裡面增加的類
EastAsianLunisolarCalendar.GetSexagenaryYear Method
EastAsianLunisolarCalendar.GetTerrestrialBranch Method
Note: Methods are new in the .NET Framework version 2.0.
Namespace: System.Globalization
Assembly: mscorlib (in mscorlib.dll)
查表也可以
Function GetYLDate(tYear As Integer, tMonth As Integer, tDay As Integer, _
YLyear As String, YLShuXing As String, _
Optional IsGetGl As Boolean) As String
On Error Resume Next
Dim daList(1900 To 2011) As String * 18
Dim conDate As Date, setDate As Date
Dim AddMonth As Integer, AddDay As Integer, AddYear As Integer, getDay As Integer
Dim RunYue As Boolean
If tYear > 2010 Or tYear < 1901 Then Exit Function '如果不是有效有日期,退出
'1900 to 1909
daList(1900) = "010010110110180131"
daList(1901) = "010010101110000219"
daList(1902) = "101001010111000208"
daList(1903) = "010100100110150129"
daList(1904) = "110100100110000216"
daList(1905) = "110110010101000204"
daList(1906) = "011010101010140125"
daList(1907) = "010101101010000213"
daList(1908) = "100110101101000202"
daList(1909) = "010010101110120122"
daList(1910) = "010010101110000210"
daList(1911) = "101001001101160130"
daList(1912) = "101001001101000218"
daList(1913) = "110100100101000206"
daList(1914) = "110101010100150126"
daList(1915) = "101101010101000214"
daList(1916) = "010101101010000204"
daList(1917) = "100101101101020123"
daList(1918) = "100101011011000211"
daList(1919) = "010010011011170201"
daList(1920) = "010010011011000220"
daList(1921) = "101001001011000208"
daList(1922) = "101100100101150128"
daList(1923) = "011010100101000216"
daList(1924) = "011011010100000205"
daList(1925) = "101011011010140124"
daList(1926) = "001010110110000213"
daList(1927) = "100101010111000202"
daList(1928) = "010010010111120123"
daList(1929) = "010010010111000210"
daList(1930) = "011001001011060130"
daList(1931) = "110101001010000217"
daList(1932) = "111010100101000206"
daList(1933) = "011011010100150126"
daList(1934) = "010110101101000214"
daList(1935) = "001010110110000204"
daList(1936) = "100100110111030124"
daList(1937) = "100100101110000211"
daList(1938) = "110010010110170131"
daList(1939) = "110010010101000219"
daList(1940) = "110101001010000208"
daList(1941) = "110110100101060127"
daList(1942) = "101101010101000215"
daList(1943) = "010101101010000205"
daList(1944) = "101010101101140125"
daList(1945) = "001001011101000213"
daList(1946) = "100100101101000202"
daList(1947) = "110010010101120122"
daList(1948) = "101010010101000210"
daList(1949) = "101101001010170129"
daList(1950) = "011011001010000217"
daList(1951) = "101101010101000206"
daList(1952) = "010101011010150127"
daList(1953) = "010011011010000214"
daList(1954) = "101001011011000203"
daList(1955) = "010100101011130124"
daList(1956) = "010100101011000212"
daList(1957) = "101010010101080131"
daList(1958) = "111010010101000218"
daList(1959) = "011010101010000208"
daList(1960) = "101011010101060128"
daList(1961) = "101010110101000215"
daList(1962) = "010010110110000205"
daList(1963) = "101001010111040125"
daList(1964) = "101001010111000213"
daList(1965) = "010100100110000202"
daList(1966) = "111010010011030121"
daList(1967) = "110110010101000209"
daList(1968) = "010110101010170130"
daList(1969) = "010101101010000217"
daList(1970) = "100101101101000206"
daList(1971) = "010010101110150127"
daList(1972) = "010010101101000215"
daList(1973) = "101001001101000203"
daList(1974) = "110100100110140123"
daList(1975) = "110100100101000211"
daList(1976) = "110101010010180131"
daList(1977) = "101101010100000218"
daList(1978) = "101101101010000207"
daList(1979) = "100101101101060128"
daList(1980) = "100101011011000216"
daList(1981) = "010010011011000205"
daList(1982) = "101001001011140125"
daList(1983) = "101001001011000213"
daList(1984) = "1011001001011A0202"
daList(1985) = "011010100101000220"
daList(1986) = "011011010100000209"
daList(1987) = "101011011010060129"
daList(1988) = "101010110110000217"
daList(1989) = "100100110111000206"
daList(1990) = "010010010111150127"
daList(1991) = "010010010111000215"
daList(1992) = "011001001011000204"
daList(1993) = "011010100101030123"
daList(1994) = "111010100101000210"
daList(1995) = "011010110010180131"
daList(1996) = "010110101100000219"
daList(1997) = "101010110110000207"
daList(1998) = "100100110110150128"
daList(1999) = "100100101110000216"
daList(2000) = "110010010110000205"
daList(2001) = "110101001010140124"
daList(2002) = "110101001010000212"
daList(2003) = "110110100101000201"
daList(2004) = "010110101010120122"
daList(2005) = "010101101010000209"
daList(2006) = "101010101101170129"
daList(2007) = "001001011101000218"
daList(2008) = "100100101101000207"
daList(2009) = "110010010101150126"
daList(2010) = "101010010101000214"
daList(2011) = "101101001010000214"
AddYear = tYear
RunYue = False
If IsGetGl Then
AddMonth = Val(Mid(daList(AddYear), 15, 2))
AddDay = Val(Mid(daList(AddYear), 17, 2))
conDate = DateSerial(AddYear, AddMonth, AddDay)
AddDay = tDay
For i = 1 To tMonth - 1
AddDay = AddDay + 29 + Val(Mid(daList(tYear), i, 1))
Next i
'MsgBox DateDiff("d", conDate, Date)
setDate = DateAdd("d", AddDay - 1, conDate)
GetYLDate = setDate
tYear = Year(setDate)
tMonth = Month(setDate)
tDay = Day(setDate)
Exit Function
End If
CHUSHIHUA:
AddMonth = Val(Mid(daList(AddYear), 15, 2))
AddDay = Val(Mid(daList(AddYear), 17, 2))
conDate = DateSerial(AddYear, AddMonth, AddDay)
setDate = DateSerial(tYear, tMonth, tDay)
getDay = DateDiff("d", conDate, setDate)
If getDay < 0 Then AddYear = AddYear - 1: GoTo CHUSHIHUA
' addday = NearDay
AddDay = 1: AddMonth = 1
For i = 1 To getDay
AddDay = AddDay + 1
If AddDay = 30 + Mid(daList(AddYear), AddMonth, 1) Or (RunYue And AddDay = 30 + Mid(daList(AddYear), 13, 1)) Then
If RunYue = False And AddMonth = Val("&H" & Mid(daList(AddYear), 14, 1)) Then
RunYue = True
Else
RunYue = False
AddMonth = AddMonth + 1
End If
AddDay = 1
End If
Next
md$ = "初一初二初三初四初五初六初七初八初九初十十一十二十三十四十五十六十七十八十九二十廿一廿二廿三廿四廿五廿六廿七廿八廿九三十"
dd$ = Mid(md$, (AddDay - 1) * 2 + 1, 2)
mm$ = Mid("正二三四五六七八九十寒臘", AddMonth, 1) + "月"
YouGetDate = DateSerial(AddYear, AddMonth, AddDay)
tiangan$ = "甲乙丙丁戊已庚辛壬癸"
dizhi$ = "子醜寅卯辰巳午未申酉戌亥"
Dim ganzhi(0 To 59) As String * 2
For i = 0 To 59
ganzhi(i) = Mid(tiangan$, (i Mod 10) + 1, 1) + Mid(dizhi$, (i Mod 12) + 1, 1)
'ff$ = ff$ + ganzhi(i)
Next i
'MsgBox ff$, , Len(ff$)
YLyear = ganzhi((AddYear - 4) Mod 60)
shu$ = "鼠牛虎兔龍蛇馬羊猴雞狗豬"
YLShuXing = Mid(shu$, ((AddYear - 4) Mod 12) + 1, 1)
If RunYue Then mm$ = "閏" + mm$
GetYLDate = mm$ + dd$
End Function
'下面是一個使用的例子,你需要在窗體上加上一個按扭,並命名為Command1,然後將下列程式碼複製到窗體的程式碼中
Private Sub Command1_Click()
Dim ty As Integer, tm As Integer, td As Integer, yl As String, sx As String
'取公曆1999年10月28日的農曆日期
ty = 1999
tm = 10
td = 28
t = GetYLDate(ty, tm, td, yl, sx)
MsgBox t
MsgBox ty & "-" & tm & "-" & td & " " & yl & " " & sx
'取1999年農曆十月28的公曆日期
t = GetYLDate(ty, tm, td, yl, sx, True)
MsgBox t
MsgBox ty & "-" & tm & "-" & td & " " & yl & " " & sx
End Sub
問:我要寫一個COM元件供asp呼叫,我能否在COM元件中得到當前呼叫ASP的客戶IP/呼叫URL等資訊?不採用傳遞引數的方法
答:可以,但是這會使你的元件依賴於IIS支援。參考
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnasp/html/comp.asp
和http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iissdk/iis/ref_biobj_cppirqs.asp
問:在ActiveX裡面寫了一個方法來呼叫javascript方法
//向js傳送資訊
LRESULT CFXVTDoc::outputParam(CString fuctionName,const CArray<CString> ¶ms)
{
extern IDispatch *pScript;
if(pScript==NULL){
return -1;
}
CComBSTR bstrMember(fuctionName);
DISPID dispid;
HRESULT hr=pScript->GetIDsOfNames(IID_NULL,&bstrMember,1,LOCALE_SYSTEM_DEFAULT,&dispid);
if(FAILED(hr)){
#ifdef _DEBUG
switch(hr)
{
case E_OUTOFMEMORY:
MessageBox(NULL,"E_OUTOFMEMORY","outputParam Err",0);
break;
case DISP_E_UNKNOWNNAME:
MessageBox(NULL,"DISP_E_UNKNOWNNAME","outputParam Err",0);
break;
case DISP_E_UNKNOWNLCID:
MessageBox(NULL,"DISP_E_UNKNOWNLCID","outputParam Err",0);
break;
}
#endif
return -1;
}
DISPPARAMS dispparams;
memset(&dispparams, 0, sizeof dispparams);
int paramNum=params.GetCount();
VARIANT *pParams=new VARIANT[paramNum];
for( int i = 0; i<paramNum; i++)
{
CComBSTR bstr =params.GetAt(i); // back reading
bstr.CopyTo(&pParams[i].bstrVal);
pParams[i].vt = VT_BSTR;
}
dispparams.rgvarg = pParams;
dispparams.cNamedArgs = 0;
dispparams.cArgs=paramNum;
EXCEPINFO excepInfo;
memset(&excepInfo, 0, sizeof excepInfo);
CComVariant vaResult;
UINT nArgErr = (UINT)-1; // initialize to invalid arg
hr = pScript->Invoke(dispid,IID_NULL,0,DISPATCH_METHOD,&dispparams,&vaResult,&excepInfo,&nArgErr);
delete []dispparams.rgvarg;
return 1;
}
這個方法在主執行緒中呼叫一切正常,但到了自己寫的執行緒中呼叫就會失敗,爆出DISP_E_UNKNOWNNAME錯誤。查了好久,看到別人的貼子上說有些com方法是執行緒不安全的,所以不要用執行緒。是這樣嗎?
可我現在不用執行緒就不知道該怎麼做。
我這裡一個操作過程是這樣的。
activex呼叫js方法--->js做相應的操作-->js呼叫activex方法報告操作完成
整個過程是不可以重疊的。比如在第一次js方法呼叫後,如果還沒有得到js的完成訊息,是不可以啟動二次js方法呼叫的。但這個對使用者來說是透明的,使用者可以一次提交多個操作請求。
所以我把操作請求放到佇列中,通過CEvent來實現同步。如果不放到執行緒中就會出現在同步等待的時候介面死掉。
這個怎麼解決?
答:你可以列集你的所有指令碼操作到建立控制元件的那個執行緒。通常的做法是傳送自定義訊息,以控制元件的視窗控制代碼為引數,在控制元件的視窗過程中編寫處理程式碼。
問:AxWebBrowser中如果JavaScrip呼叫關閉視窗的命令會觸發什麼事件?我用AxWebBrowser控制元件瀏覽下面這個網頁,http://www.5460.net/gy5460/jsp/login/loginMain.jsp,點選關閉按鈕,網頁呼叫JavaScript中的window.close()方法,請問我如何截獲這個事件。謝謝。我監視window.close()執行前後,實際上axWebBrowser控制元件並沒有關閉,各個屬性和執行前完全一樣,但是當我呼叫browser.visible=true,browser.BringToFront()函式時,瀏覽器雖然能重現,但是卻無法再瀏覽網頁了。請問這是為什麼?好像用JavaScript關閉瀏覽器控制元件時,瀏覽器控制元件應該釋放資源了,可是除錯的時候還能發現其內部資訊沒有丟失,真是奇怪!
答:會有windowclosing.事件http://msdn.microsoft.com/workshop/browser/webbrowser/reference/events/windowclosing.asp。處理windowclosing事件,取消預設的過程,自行提示使用者和關閉視窗就可以了。
參考
Q253219 PRB: WebBrowser Control Disappears When Script Calls window.close()
http://support.microsoft.com/support/kb/articles/q253/2/19.asp
問:如何初始化ocx控制元件的大小? 以及控制元件大小被改便後,是通過什麼訊息響應的?
答:如果你需要設定ActiveX的大小,可以參考
MFC控制元件:http://support.microsoft.com/kb/168326
ATL控制元件:http://support.microsoft.com/kb/242994
更多資訊可以參考http://msdn.microsoft.com/library/en-us/dnaxctrl/html/msdn_contcntr.asp
問:在COM元件裡經常要加入一些新的類,而呼叫COM元件的客戶程式不知道這些類的具體結構,希望每次在COM加入新類時,客戶程式通過讀一個配置檔案(這個檔案中記錄著COM中類名稱和類中域和方法的名稱),就能例項COM中的類,並呼叫類的方法。請問如何做才能使客戶程式在每次COM中加入新類時都不必進行擴充套件並重新編譯?如果COM沒有辦法,還有沒有其他技術可以完成?謝謝回答。
答:你可以讓伺服器端支援OLE自動化,客戶整合一個指令碼引擎就可以了。微軟的指令碼引擎支援JScript和VBScript
問:我寫了一個b/s結構的程式,用VB寫了一個程式把b/s的頁面包含在裡面,用的是webbroser控制元件,現在問題出來了,以前頁面裡面的開啟新視窗教本:window.open(url),彈出來的仍然是IE視窗,請問各位大俠,有沒有辦法在b/s頁面裡面用教本控制開啟的新視窗為VB的form。麻煩各位了~~~
答:VB6不能實現這個功能。你可以用ATL實現IDocHostUIHandler::GetExternal和IDocHostUIHandler::SetExternal,然後在VB中設定,就可以在網頁的指令碼中通過訪問webbrowser.Document.external來訪問設定的物件。
參考
http://support.microsoft.com/kb/183235/
http://www.csdn.net/develop/read_article.asp?id=48483
問:如何獲取某正在執行程式資料區的記憶體開始地址和記憶體長度?
答:Windows裡面可以用VirtualQueryEx嘗試獲得已經提交的記憶體頁的資訊。參考http://community.csdn.net/Expert/topic/3801/3801409.xml?temp=.3144037和http://www.csdn.com.cn/program/4603.htm
問:我的ActiveX控制元件是內嵌入IE的,我想當這個IE頁面失去/獲取當前焦點的時候告訴我這個ActiveX控制元件,不知道在htm裡有沒有這樣的事件。我這裡所說的“當前焦點”是指當前使用者檢視的是哪個頁面,當前檢視的htm頁面既具有當前焦點!
答:判斷GetForegroundWindow所線上程就可以……