http://hpcgi1.nifty.com/MADIA/Vcbbs/wwwlng.cgi?print+200707/07070029.txtより、私の回答スタイルを全否定されました。
プログラマって、何かを作るってことに達成感を持ちませんかね?
パズルのようにあるピースとピースをつないでゆく、そういうところが面白いと思うんだけど。
何もネタがなかったので久々の更新です。
皆々様のおかけで、Visual Developer - Visual C++のカテゴリで
マイクロソフト MVP アワードを受賞することができました。
MVPという重圧に恥じぬように日々精進しなければ。。。
MSDNフォーラムでMC++の質問のために、VS2005のCLR Windowsフォームアプリケーションを
/clr:oldSyntaxで、コンパイルできるように書き直したのですが、
これはデザイン画面使えなくなっちゃうかなぁ~と思ったけど、そうでもなかったです。
コントロールの配置からイベントまで自動生成されるコードはすべてMC++用になるんですな。
いろいろ便利になっているのかなと思ったら、新しいフォームとかのCLRコンポーネントは追加できない
ようです。
ですので、追加時は/clrを変更してから、自動生成されたコードをMC++用に書き直し、
再度/clr:oldSyntaxに戻すようなことをしないとだめなのかな。(ここまで面倒見てほしかった。)
# タイトル長かったので短くしたw
前回Windows フォームアプリケーションで #importをつかってExcelを使おうとすると、
vtMissingをつかうようなメソッドを使うと、ASSERTして実行できない現象がありました。
そこでデバッガでさかのぼっていったところ、
ってなのをみつけ、もしかしたらvtMissingが作成できていないとか?と適当なことを思いつき
グローバル変数として _variant_t vtMissing; を入れてみたら、よくわからないけどASSERTもなく動きました!
# extern _varinat_t vtMissing;はcomutil.hに記述されていますが、その定義はどこに記述されているのだろ?
# (記述されていなければリンクエラーになるはずなんだけど。)
この対処でありなんだろうか?
最近 C++/CLI でも Excel を操作したいという質問をよく見ます。
そこでサンプルでも作っておこうかなとおもって、いろいろやってみたのですが、
CLRプロジェクト-Windows フォームアプリケーションのときに、ある条件のときに実行できなくなります。
(コンパイルはできる)
以下そのコードです。Formも立ち上がらずすぐにASSERTします。
(ちなみに、CoInitializeは(何でかはよくわからないけど)不要のようです。)
#import "C:\Program Files\Common Files\Microsoft Shared\OFFICE11\MSO.DLL" \
no_namespace rename("DocumentProperties", "DocumentPropertiesXL") \
rename("RGB", "MSO_RGBXL")
#import "C:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB" \
no_namespace
#import "D:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE" \
rename("ReplaceText", "ReplaceTexXL") rename("CopyFile", "CopyFileXL") \
rename("DialogBox", "DialogBoxXL" ) rename("RGB", "RGBXL")\
rename("DocumentProperties", "DocumentPropertiesXL") \
exclude("IFont") exclude("IPicture") no_dual_interfaces
HRESULT ExcelTest()
{
HRESULT hr = S_OK;
Excel::_ApplicationPtr pApp = NULL;
try
{
hr = pApp.CreateInstance(L"Excel.Application");
if (FAILED(hr)) _com_issue_error(hr);
Excel::WorkbooksPtr pWorkbooks = pApp->GetWorkbooks();
if (pWorkbooks)
{
Excel::_WorkbookPtr pWorkbook = pWorkbooks->Add();
if (pWorkbook)
pWorkbook->Close();
}
pApp->Quit();
}
catch (_com_error& e)
{
hr = e.Error();
}
if (pApp) pApp.Release();
return hr;
}
環境:Visual Studio 2005 Pro SP1/Windows Xp Pro SP2/Excel 2003 Personal SP2
オプション:Unicode 文字セットを使用する, 共通言語ランタイム サポート (/clr)
(一応ソースは分けてあります。(ExcelTest.cpp))
これをCLRコンソールアプリケーションで記述し動かしても何も問題ありません。
で、本題の
>ある条件のときに
とは、引数省略時のvtMissingではなかろうか?と思っています。
上のコードの Excel::Workbooks::Add と Excel::Workbook::Close をコメントアウトすると正常に実行できます。
また、
>Excel::_WorkbookPtr pWorkbook = pWorkbooks->Add();
を
Excel::_WorkbookPtr pWorkbook = pWorkbooks->Add(Excel::xlWBATWorksheet);
にして、Excel::Workbook::Close をコメントアウトしても正常に実行できます。
>pWorkbook->Close();
を
_variant_t v;
pWorkbook->Close(v);
としても実行できません。
ASSERTは
D:\Program Files\Microsoft Visual Studio 8\VC\crt\src\dbgheap.c の 1473 で発生し、ちょっと理解しにくそうなものです。
>_ASSERTE(_CrtIsValidHeapPointer(pUserData));
一応、#pragma unmanged とか、試してみたけど意味なしっぽく、お手上げ状態です、、、
もう少しやってみて、だめなら掲示板にスレたてますかな。
(常識かもしれませんが、)
先日、SHBrowseForFolder のデフォルトパスにネットワークパスを指定するには?の質問にて、
VB6で指定のディレクトリのLPITEMIDLISTの値を取得する方法をいろいろ調べていたところ、
(VC++ならIShellFolder::ParseDisplayNameで取得できる)
K.J.Kさんから
Private Declare Function SHGetIDListFromPath _
Lib "shell32.dll" Alias "#28" _
( _
ByRef Path As Byte, _
ByRef RetPIDL As Long, _
ByRef RetAttr As Long _
) As Long
ってな関数を使う方法があるのを教えてもらいました。
#28 って何やねん!と思って調べてみたところ、「エントリポイントの序数指定」とのことでした。
つーことは、Win32APIのGetProcAddress関数もできるのかなと調べてみたところ、ちゃんのMSDNに載っていました。
(.NET FrameworkのDllImportでも同様→エントリ ポイントの指定? )
とっても勉強になりました。
だけど、こういう隠し的な関数は本当に知っていないと使えない罠。(引数やら戻り値やらが隠蔽されているので)
ちなみに、.NET FrameworkのFolderBrowserDialogでは任意(ネットワークパス含み)のルートや初期ディレクトリを設定することは
できないのかな?
追記
shell32.dllの序数28番目の関数名ですが、
SHILCreateFromPath
だそうです。
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/functions/shilcreatefrompath.asp
ついでに、SHGetIDListFromPathでぐぐったときに#162ってのを見かけたが
あれも、
SHSimpleIDListFromPath
って関数名でした。
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/functions/shsimpleidlistfrompath.asp
# 本当はコメントでレスしようかと思ったけど、なぜかsubmitできなかったので追記編集で。
VC2005で気になったこと。
MFCの~A、~Wのあるメソッドで、どうも~Wしかインテリセンスで表示されないような。
(~Aや~Wのつかないものが表示されない)
※一部のクラスのメソッドで文字セット:Unicodeでしか試していません。
VC2005(VS2005 Pro)

↑
の場合、GetWindowTextってのは候補にないの?ってことです。
(実際は使えます。)
参考(VC6 Stand)

ちなみに windows.hのGetWindowTextの場合は3つとも表示されます。

編集追記)
よく考えると、CWnd::GetWindowTextと宣言されているものの
GetWindowTextが#defineで置き換わった後のものを表示しているような気がします。
(ということで、_MBCSの場合はGetWindowTextAしか出ないわけなのかな。)
まぁ一番問題なのは、折角TCHARとして使っているのにもかかわらず、
GetWindowTextWとか使っちゃったら、_MBCSではコンパイルできなくなってしまうということです。
(TCHARを理解していない人ははまりそうですな。)
ある掲示板で、「String^型をchar型配列にするにはsprintfを使えばいい」というのを見ました。
実際試してみるとうまくいっているようには見える。
ただ、可変長引数にString^型を渡す?そんなのやっていいの?って疑問が出ました。
実験コード
#include <cstdarg>
#include <cstdio>
#pragma unmanaged
void test1( char* first, ... )
{
char* letter = first;
va_list args;
va_start( args, first );
while ( letter != 0 )
{
printf( "'%s'\n", letter );
letter = va_arg( args, char* );
}
va_end( args );
}
#pragma managed
int main()
{
System::String^ s = L"漢字ひらがなEIJI1234+/?";
test1( "てすと", s, 0 );
return 0;
}
var_arg( args, char* )のようにchar*型で受ければうまいこと変換されているのかなぁ。(なんでだろ?)
(ということで、swprintfは使えないようだ。)
どうも、お世話になります。
Blueといいます。
前々からこちらの掲示板等を利用させていただき、
いつかは加盟させてもらおうと思っていましたところ、じゃんぬさんに誘われたので
思い切って入っちゃいました。
自分は、ネタ発信できるほどではないので、なんとなく掲示板やらで感じたこととかを
載せていこうかなぁと思っています。
定期的に更新できる自身はないですw→(相当のめんどくさがり屋ですので)
今なら質問受け付けます。といってみるテストw