ホーム » メモ (ページ 18)
「メモ」カテゴリーアーカイブ
クリップボードに…
オフスクリーンにレンダリングしたものをクリップボードにコピーしていて,
5000x5000x4 バイトの CF_BITMAP がうまく動作しない.
原因は Office クリップボードの制限みたいで 8 M まで.
Office クリップボードにアイテムを追加できない場合の確認事項
無効にして対応.
よくわからないが,以下の様にした.
CF_METAFILEPICT StretchDIBits
CF_BITMAP AlphaBlend
AlphaBlend function (Windows) – TechNet – Microsoft に,
An error occurs (…) if the source device context identifies an enhanced metafile device context.
コピー画像は,
いろいろやっていて,一度 EMF に吐いて
::GetEnhMetaFile(…) で返される HENHMETAFILE を CF_ENHMETAFILE で意図した動作となった.
{
CString tmpPath = ::GetTempPath() ;
tmpPath = CString(::Path_AddLastSP(tmpPath).c_str()) + _T(“Debug.tmp”) ;
tmpPath = CString(::Path_AddLastSP(tmpPath).c_str()) + ::GetFileTitle(::GetModuleFileName()) ;
CString nowStr = CTime::GetCurrentTime().Format(_T(“%d%H%M%S”)) ;
CString tmpName = CString(::Path_AddLastSP(tmpPath).c_str()) + nowStr + _T(“.emf”) ;
::CreateFolder(tmpPath) ;
::ToEMF(dib,tmpName) ;
HENHMETAFILE hMetaFile = ::GetEnhMetaFile(tmpName) ;
return hMetaFile ;
}
…
::SetClipboardData(CF_ENHMETAFILE, hGMemEnhM) ;
i_DIB_x.hxx
i_DIB_Fn.hxx
i_dib.hxx
今度はメモリメタファイル(第 2 引数を NULL)にして,
{
CMetaFileDC mf_DC ;
BOOL ret = mf_DC.CreateEnhanced(NULL,NULL,NULL,NULL) ;
::AlphaBlend (mf_DC.GetSafeHdc(),dRect,dib) ;
HENHMETAFILE hEnhMetaF = mf_DC.CloseEnhanced() ;
return hEnhMetaF ;
}
CreateEnhanced の幾つかの引数が NULL は知らなかった.
CreateEnhMetaFile
Programming Windows 5 18.2.2
Programming Windows 5
XP 環境のクリップブックや,Word 2003 などでの CF_METAFILEPICT がうまくない.
{
CMetaFileDC mf_DC ;
BOOL ret = mf_DC.Create() ;
::StretchDIBits (mf_DC.GetSafeHdc(),dRect,dib) ;
HMETAFILE hMetaFile = mf_DC.Close() ;
hGMemMeta = ::GlobalAlloc( GHND, (DWORD) sizeof(METAFILEPICT)) ;
{
LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)GlobalLock(hGMemMeta) ;
lpMFP->mm = MM_TEXT ;
lpMFP->xExt = dRect.right ;
lpMFP->yExt = dRect.bottom ;
lpMFP->hMF = hMetaFile ;
}
::GlobalUnlock(hGMemMeta) ;
return hGMemMeta ;
}
StretchDIBits とした.
Win 10 TP 10061
Build 10061 に更新.
VirtualBox だからなのかわからないが,OpenGL を利用している exe で真っ黒になってしまう.
Vista になった時,一部の環境やオフスクリーンの場合に同様の現象だったと記憶している.
DescribePixelFormat , SetPixelFormat 辺り?
Build 9926 では問題なかったと思う(9879 では問題ない).
exe によっては起動しなかったり,アプリケーションエラーになる.
他に,どこかの設定かわからないが,エクスプローラから AP にドキュメントのドロップが出来ない?
2015/06/03
Build 10130 で,OpenGL での描画が真っ黒になる動作は解消されている.
vsdrfCOM でエラー
VS 2005 のセットアッププロジェクトで,exe の「Register」を「vsdrfCOM」としてビルドすると,
—————————
AsTM0317.exe – アプリケーション エラー
—————————
“0x5cac9a9c” の命令が “0x0000005c” のメモリを参照しました。メモリが “read” になることはできませんでした。
プログラムを終了するには [OK] をクリックしてください
—————————
OK
—————————
—— ビルド開始: プロジェクト: TestSet3, 構成: Debug ——
ファイル ‘C:\…\TestSet3\TestSet3\Debug\TestSet3.msi’ をビルドしています…
警告: ‘AsTM0317.exe’ というファイルのレジストリ情報を作成できません。
警告: Windows インストーラは、どの選択された必須コンポーネントにも含まれていません。
ファイル ‘AsTM0317.exe’ をパッケージしています…
ファイル ‘AsImgCnv.exe’ をパッケージしています…
========== ビルド: 1 正常終了または最新の状態、0 失敗、0 スキップ ==========
AsImgCnv.exe の方はエラーの表示はない.
VS 2002 や 2008 では,OK.
また,vsdrfCOMSelfReg の場合も OK.
2015/03/20
vsdrfCOMSelfReg とした場合,そのままではインストール時にダイアログから表示されていた.
/RegServer , /UnRegServer が指定された場合,ダイアログを表示しない様に対応.
BOOL isReg = FALSE ;
{
if (::FindNoCase(m_lpCmdLine,_T( “/REGSERVER”)) >= 0) { isReg = TRUE ; }
else if (::FindNoCase(m_lpCmdLine,_T( “-REGSERVER”)) >= 0) { isReg = TRUE ; }
else if (::FindNoCase(m_lpCmdLine,_T(“/UNREGSERVER”)) >= 0) { isReg = TRUE ; }
else if (::FindNoCase(m_lpCmdLine,_T(“-UNREGSERVER”)) >= 0) { isReg = TRUE ; }
}
if (!isReg) {
CAsImgCnvDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK) {
}
else if (nResponse == IDCANCEL) {
}
}
IIS 環境の再設定
2019/12 Win10 IIS 環境に Classic ASP のインストールと設定
2020/10 https://jml.mish.work/various/iis.html
AsTrmM_VC8 が動作しない.
—————————
Microsoft Visual C++ Runtime Library
—————————
Runtime Error!
Program: C:\Temp\…\Release.080\AsTM0129.exe
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application’s support team for more information.
—————————
OK
—————————
AsTrmM_VC6 は OK .
どうも OpenMP がうまくない?
Win 7 で,Classic ASP は「World Wide Web サービス」-「アプリケーション開発機能」-「ASP」をチェック.
Win10 Classic ASP インストール
以前 XP に設定した時のメモ.
Web ページの公開
2015/02/16
asp ファイルが存在する所を開くと,
サーバー エラー
500 – 内部サーバー エラーです。
検索中のリソースに問題があるため、リソースを表示できません。
サーバ側で動かすと,
An error occurred on the server when processing the URL. Please contact the system administrator.
If you are the system administrator please click here to find out more about this error.
どうもデフォルトでは出力されなくなったみたい.
今度は次の様なコードで実行時エラー.
dim oToPA
set oToPA = Server.CreateObject(“PAto.AsXxx”)
Microsoft VBScript 実行時エラー エラー ‘800a01ad’
ActiveX コンポーネントはオブジェクトを作成できません。
/Test/Test_1st/DrawVer.asp, 行 6
Win XP では ActiveX.exe を起動すれば良かったが,Win 7 では「管理者」とする必要があるので,
「コマンドプロンプト」を「管理者として実行」して,その中で exe を起動.
アクセス権が許可されてないと,
Server オブジェクト エラー ‘ASP 0178 : 80070005’
Server.CreateObject アクセス エラー
/Test/Test_1st/DrawVer.asp, 行 6
許可を確認中に Server.CreateObject の呼び出しに失敗しました。
このオブジェクトへのアクセスは拒否されます。
アクセス権を設定.
Win 7 では IUSER .
OS が 64 ビットの時,そのままでは ActiveX.dll が起動しない.
他の PC から,http://win7-iis:8080/ の様に接続できない(localhost:8080 は可能).
対応方法がよくわからないが,ファイアウォールの設定で 8080 を追加してみたら通る様になった.
2015/02/17
サーバのオートメーション機能で ini に設定値を保持しているが更新されない
(IUSER はフルコントロールとして存在している).
Everyone の追加で意図した動作(ini を更新できる)にはなった.
‘新しいテキスト ドキュメント.txt’ …
ちょっと変な状態に陥ったのでメモ.
\\DevS\Documents\MICS\Plan\MICSDat\Test_2015 01-03\9LM-2U-J6TRi-2S7M.001\
\\DevS\Documents\MICS\Plan\MICSDat\Test_2014_12\ などでは
[Window Title]
ファイルを作成できません
[Content]
ファイル ‘新しいテキスト ドキュメント.txt’ を作成できません。
開かれている共有ファイルが多すぎます。
[OK]
\\DevS\Documents\MICS\Plan\MICSDat\ だと戻ってこない(エクスプローラが応答なしになる)
\\DevS\Documents\MICS\Plan\ などでは正しく生成できる.
ログオフ時,\\DevS\Documents\MICS\Plan\MICSDat\新しいテキスト ドキュメント.txt ができていた.
再ログオン後,直後はできなかったがしばらくすると可能となった.
現象はどーってことない(再起動すれば直る)が,
問題は,MFC で作成した普通の AP でドキュメントが消失したこと.
その AP は,自動的に %Temp% にバックアップを保持するので完全に失ったわけではないが,
標準の MFC のシリアライズ動作ではうまくないのか?
コンソール AP でレジストリ読み取り
コンソール AP で,レジストリを読み取るために以下の様な関数を用意した.
int Reg_GetInt (HKEY hKey,LPCTSTR subKey,LPCTSTR ent,const int defValue=0)
{
DWORD value = defValue ;
#ifdef _ATL_VER
{
CRegKey reg ;
reg.Open(hKey,subKey) ;
#if (_ATL_VER >= 0x700)
reg.QueryDWORDValue(ent,value) ;
#else
reg.QueryValue(value,ent) ;
#endif
}
#else
{
HKEY hSecKey = NULL ;
LONG openStatus = ::RegOpenKeyEx(hKey,subKey,0,KEY_READ,&hSecKey) ;
if (hSecKey == NULL) { return value ; }
DWORD type = REG_NONE ;
DWORD count = sizeof(DWORD) ;
LONG queryStatus = ::RegQueryValueEx(hSecKey,ent,NULL,&type,(LPBYTE)&value,&count) ;
::RegCloseKey(hSecKey) ;
}
#endif
return int(value) ;
}
*::Reg~ などのエラーチェックは省いている.
呼出すのはこんな感じ.
int value = ::Reg_GetInt(HKEY_CURRENT_USER,_T(“Software\\Iwao\\Test\\RegAcc”),_T(“T_RegKey_DW”)) ;
CWinApp::GetProfileInt などが使えないかとやってみたが,…
1. AfxGetApp() を呼びだしても,NULL で戻ってくる.
次の様に領域を確保.
CWinApp theApp;
2. SetRegistryKey(key) が直接呼びだせないので,
class C_SRK_WinApp : public CWinApp {
public:
void SetRegKey (LPCTSTR key) { SetRegistryKey(key) ; }
} ;
変数の確保は次の様に変更.
C_SRK_WinApp theApp ;
3. SetRegistryKey の中で ASSERT(m_pszAppName != NULL)
以下を追加して,CWinApp を初期化.
AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0) ;
4. これで CWinApp::GetProfileInt は利用できるようになるが,CWinApp::m_pszProfileName が邪魔.
C_SRK_WinApp* app = (C_SRK_WinApp*)AfxGetApp() ;
int val = app->GetProfileInt(_T(“Test\\RegAcc”),_T(“T_RegKey_DW”),0) ;
HKCU\Software\Iwao\(m_pszProfileName)\Test\RegAcc となってしまう.
5. m_pszProfileName を _T(“”) とすることにより,意図した値を取得できる様にはなった.
C_SRK_WinApp* app = (C_SRK_WinApp*)AfxGetApp() ;
if (app != NULL) {
AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0) ;
app->SetRegKey(_T(“Iwao”)) ;
free((void*)app->m_pszProfileName) ;
app->m_pszProfileName = _tcsdup(_T(“”)) ;
int val = app->GetProfileInt(_T(“Test\\RegAcc”),_T(“T_RegKey_DW”),0) ;
}
コンソール AP で CWinApp::GetProfileInt などを使うことは,やめ.
GetDIBits
GetDIBits を利用していて,最初うまく取れなかったのでメモ.
lpvBits に NULL が指定できるとのことなので,
::GetDIBits(hDC,hbm,0,bmap.bmHeight,NULL, &bmif,DIB_RGB_COLORS) ;
しかしうまく取れない.原因は,biSize の指定がされてなかったため.
bmif.bmiHeader.biSize = sizeof(BITMAPINFOHEADER) ;
以下の様に,BITMAPINFO を求めてから,もう一度呼び出し情報は取れる様になった.
::GetDIBits(hDC,hbm,0,bmap.bmHeight,NULL, &bmif,DIB_RGB_COLORS) ;
if (::GetDIBits(hDC,hbm,0,bmap.bmHeight,&bits[0], &bmif,DIB_RGB_COLORS) != 0) {
….
}
が,bmif の部分を stack としていて,オーバーフローしている.
BITMAPINFO bmif ; memset(&bmif, 0, sizeof(BITMAPINFO)) ;
デバッグ用に,次の様に 0xfe で初期化して渡してみると
v_char bmif ; bmif.resize(sizeof(BITMAPINFO)+sizeof(RGBQUAD)*256,-2) ;
memset(&bmif[0],0, sizeof(BITMAPINFO)) ;
BITMAPINFO* pbmi = (BITMAPINFO*)&bmif[0] ;
00036C40 28 00 00 00 02 00 00 00 02 00 00 00 01 00 20 00 (............. . 00036C50 03 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 ................ 00036C60 00 00 00 00 00 00 00 00 00 00 FF 00 00 FF 00 00 ................ 00036C70 FF 00 00 00 FE FE FE FE FE FE FE FE FE FE FE FE ................
どうも,1 回目の GetDIBits で,pbmi->bmiHeader.biCompression が BI_BITFIELDS となっている.
… the color table consists of three DWORD color masks that specify the red, … とある.
以下の様に,BI_RGB を再設定する様にした.
::GetDIBits(hDC,hbm,0,bmap.bmHeight,NULL, pbmi,DIB_RGB_COLORS) ;
pbmi->bmiHeader.biCompression = BI_RGB ;
if (::GetDIBits(hDC,hbm,0,bmap.bmHeight,&bits[0], pbmi,DIB_RGB_COLORS) != 0) {
….
}
HBM_Fn.hxx
i_DIB_Fn.hxx
MessageBar クラスと OpenMP
新しい Message クラスを使用して,OpenMP 対応の動作のテスト.
void CTSttBView::OnTestDrawBar2()
{
Message tmp ;
ElapseTick et ;
#define BAR_COUNT_2 1000000
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (int i=0 ; i<100 ; i++) {
Message bar ;
bar.SetBar (_T(“Test Message 1 M * 100”),BAR_COUNT_2,RGB(0,255,0)) ;
for (int index=0 ; index<BAR_COUNT_2 ; index++) {
bar.SetBarInc() ;
}
}
DWORD elapseT = et.GetElapse() ;
CString str ; str.Format(_T(“%.2f 秒”),elapseT/1000.) ;
AfxMessageBox(str) ;
}
1 億回 SetBarInc を呼出していて,10 秒程度だったのが,#pragma omp parallel for で 20 秒程度になってしまった.
inline bool MessageBase::SetBarInc (void)
{
if (GetBarMax() == 0) { return false ; }
if (GetBarCount() < GetBarMax()) { B_Counter++ ; }
else { B_Counter = 0 ; } // reset
IncCounterR() ;
{
long lastPos = long(100*(GetBarCount()-1)/GetBarMax()) ;
long new_Pos = long(100*(GetBarCount()-0)/GetBarMax()) ;
if (lastPos == new_Pos) { return true ; }
}
#ifdef _WINDOWS
#ifdef _MFC_VER
#ifdef _OPENMP
if (AfxGetMainWnd() == NULL) { return false ; }
#endif
#endif
#endif
return SetBarCount(B_Counter) ;
}
AfxGetMainWnd() を呼出す回数を減らすことにより,3 秒程度に.
デバッグビルドで C2061 ‘_DebugHeapTag_func’
以前(2014/04/25 の exe が存在する)は通っていたのに,…
------ ビルド開始: プロジェクト: BLCombi, 構成: Debug Win32 ------ ComPrj01.cpp c:\program files (x86)\microsoft visual studio 9.0\vc\include\xlocmon(283) : error C2061: 構文エラー : 識別子 '_DebugHeapTag_func' c:\program files (x86)\microsoft visual studio 9.0\vc\include\xlocmon(281): クラス テンプレート のメンバ関数 'size_t std::moneypunct<_Elem,_Intl>::_Getcat(const std::locale::facet **,const std::locale *)' のコンパイル中 with [ _Elem=char, _Intl=true ] c:\program files (x86)\microsoft visual studio 9.0\vc\include\xlocmon(908) : コンパイルされたクラスの テンプレート のインスタンス化 'std::moneypunct<_Elem,_Intl>' の参照を確認してください with [ _Elem=char, _Intl=true ] BLCombi - エラー 1、警告 1
------ ビルド開始: プロジェクト: BLCombi, 構成: Debug Win32 ------ ComPrj01.cpp c:\program files\microsoft visual studio 8\vc\include\xlocmon(273) : error C2061: 構文エラー : 識別子 '_DebugHeapTag_func' c:\program files\microsoft visual studio 8\vc\include\xlocmon(271): クラス テンプレート のメンバ関数 'size_t std::moneypunct<_Elem,_Intl>::_Getcat(const std::locale::facet **)' のコンパイル中 with [ _Elem=char, _Intl=true ] c:\program files\microsoft visual studio 8\vc\include\xlocmon(887) : コンパイルされたクラスの テンプレート のインスタンス化 'std::moneypunct<_Elem,_Intl>' の参照を確認してください with [ _Elem=char, _Intl=true ] BLCombi - エラー 1、警告 0
------ ビルド開始 : プロジェクト : BLCombi, 構成 : Debug Win32 ------ ComPrj01.cpp c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\xlocmon(249) : error C2061: 構文エラー : 識別子 '_DebugHeapTag' c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\xlocmon(247): クラス テンプレートのメンバ関数 'size_t std::moneypunct<_Elem,_Intl>::_Getcat(const std::locale::facet ** )' のコンパイル中 with [ _Elem=char, _Intl=true ] c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\xlocmon(828) : コンパイルされたクラスのテンプレートのインスタンス化 'std::moneypunct<_Elem,_Intl>' の参照を確認してください with [ _Elem=char, _Intl=true ] BLCombi - エラー 1、警告 0
------ ビルド開始 : プロジェクト : BLCombi, 構成 : Debug Win32 ------ ComPrj01.cpp c:\Program Files\Microsoft Visual Studio .NET\Vc7\include\xloctime(539) : error C2061: 構文エラー : 識別子 '_DebugHeapTag' c:\Program Files\Microsoft Visual Studio .NET\Vc7\include\xloctime(539) : error C2143: 構文エラー : ';' が ')' の前にありません。 BLCombi - エラー 2、警告 0
VC 6 や VC 10 , 11 , 12 では 通る.
検索すると, #define new DEBUG_NEW の定義の様であるが,この ComPrj01.cpp でどうすべきかが不明.
本来は,ComPrj01.cpp でインクルードしているファイルを変更すべきなのだろうが,いい方法がわからない.
ComPrj01.cpp でインクルードしているものの順番を変更することで,通る様にはなった.
2024/11/11
https://dev.mish.work/wordpress/?s=C2061
xcode + glut
「Command Line Tool」としてプロジェクトを作成.
「GLUT」を追加.
10.9 になったこと?により出力される次の様なワーニングをでない様にするために 10.8 に.
/Users/Iwao/…/main.cpp:116:2: ‘glutInit’ is deprecated: first deprecated in OS X 10.9
インクルードパス設定場所は,「Build Settings」−「Search Paths」−「Header Search Paths」
glut.h のインクルードは以下の様にしている.
#ifdef __APPLE_CC__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
OpenGL Programing Guide
何年も前に買った本(1995年8月10日第4刷となってる)で,中に含まれるサンプルを実行できる様にしてみた.
OpenGL Programing Guide
サンプルのソースで,<gl\glut.h> のインクルードは最初に移動.
glut
opengl.org
GLUT and OpenGL Utility Libraries
GLUT – The OpenGL Utility Toolkit
Nate Robin’s GLUT for Windows page
glut32.dll は,system32 などへ.
glut.h は,~\Include\gl へ.
glut32.lib は,~\Lib へ.
セレクション
::glRenderMode(GL_SELECT) の後の ::glRenderMode(GL_RENDER) で,セレクションヒット数が得られる.
::glGetIntegerv(GL_RENDER_MODE) で現在のモードを取得可能.
セレクションバッファの内容
名前の深さ?
Z min
Z max
名前 …
2014/09/04
時間がかかったがなんとか GLUT ではできた.
2014/09/08
今度は,VXxxxView を使用した SDI.exe での手順.
ビューの OnDropFiles で,ファイルの種類により glRenderMode GL_SELECT , GL_RENDER を呼ぶ様に変更.
CMainFrame::OnDropFile で条件により CXxxxView::OnDropFile を呼び出し.
glGetIntegerv(GL_RENDER_MODE,…) で GL_SELECT が返ってこない.
wglMakeCurrent を呼んでなかったので,効果がなかった.
今度は,GL_SELECT にならない.GL_INVALID_OPERATION となる.
ヘルプにある様に,glSelectBuffer を呼んでなかった.
CPickSView::OnDropFiles
GetOpGLP()->MakeCurrent(TRUE) ;
if (…) {
::glSelectBuffer(BUFSIZE,selBuf) ;
::glRenderMode(GL_SELECT) ;
}
else {
::glRenderMode(GL_RENDER) ;
}
GetOpGLP()->MakeCurrent(FALSE) ;
2014/09/10
PickS.2014.09.09.zip
マウスの Y 方向の位置が合ってない.
その exe を Win 7 環境で動かすと,
デバッグ用に ::glGetIntegerv(GL_RENDER_MODE,…) のために GetOpGLP()->MakeCurrent(…) していた.
MakeCurrent(FALSE) で SwapBuffers を呼んでいる.
マウスの Y 方向は,縦長だと合っていそう.横長だとその長い分だけ Y 方向にずれている?
コの字型の平面方向で,座標はそれなりにとれている.::gluUnProject の z は Depth / 0xffffffff .
gulUnProject の y の与え方が違っていた.
viewPort[3] – pt.y としていたが,それではダメみたいで,GetClientRect の Height() としてうまくいってそう.
PickS.2014.09.10.zip
まだ ::gluPickMatrix の方がうまくできてない.
2014/09/11
平面図にして,1 つの直方体がウィンドウいっぱいに表示される状態で選択すると,
どうもピック領域のサイズが,ウィンドウの大きさになっているような感じ.
20 Picking and Using Selection 20. ピッキングとセレクションの使い方 を参考にしているが,…
::gluPickMatrix を呼ぶタイミングが悪かったのが原因.
ある程度予想はしていたが,OpGL::Projection の中のため,その関数を分割する必要がありそう.
その関数内の OpenGL の呼び出しは,
::glMatrixMode(GL_PROJECTION) ;
::glLoadIdentity() ;
// ここ
::glOrtho(r.l,r.r,r.b,r.t, zNear,zFar) ; / ::gluPerspective(deg(angle),aspect, zNear,zFar) ;
::glViewport((GLint)win.l,(GLint)win.b,(GLint)(win.r-win.l),(GLint)(win.t-win.b)) ;
glLoadIdentity() の後に ::gluPickMatrix を呼ばなければならない.
PickS.2014.09.11.zip
2014/09/18
汎用的なコードにするため,コードを見直しているがなかなか進まない.
例えば,マウスの移動で選択されているものを表示しようとすると,テクスチャありでは遅くて使えない.
また,その時の表示で PgonsA の描画を抜き出したコードだと何とか見れるが PartsA::Draw 相当だと遅い.
PickS.2014.09.18.zip
COleDataSource を利用した Drag
以前 DoDragDrop で少し調べたが,その時は途中になっていた.
その時の内容で,例えば CListBox に表示されてるファイルリストのすべてを,CListBox の外側でドラッグするすることはできる.
void CDragLBDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
CStringArray sa ;
::ToStringArray(FileNames,&sa) ;
::StringArrayToDoDragFiles(sa) ;
}
CListCtrl であれば,OnBegindragXxxx が利用できるので,
void CDragLVDlg::OnBegindragListFiles(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
{
CStringArray sa ;
for (int index=0 ; index<m_ListFiles.GetItemCount() ; index++) {
if (m_ListFiles.GetItemState(index,LVIS_SELECTED) == LVIS_SELECTED) {
tstring str = FileNames[index] ;
sa.Add(str.c_str()) ;
}
}
if (sa.GetSize() > 0) {
::StringArrayToDoDragFiles(sa) ;
}
}
*pResult = 0;
}
今回やりたかったのは,CListBox の項目のドラッグ.
ドラッグ部分は CListCtrl とほぼ同様となると思われるが,ドラッグ開始のタイミングが取れない.
CDragListBox と開始時の動きは似ているが,MFC のコードを見るとちょっと難しそう.
いろいろと検索すると,CListBox のサブクラス化で対応するみたいとわかったが,手順が...
動的なサブクラス化と言うらしい.
Inside Visual C++ には,囲み記事に CNonNumericEdit がある.
利用する手順はわかるが,作成する手順がわからない
今も利用はしている CView からの VXxxxView ファミリがあるが,10 年以上前で手順は覚えてない.
いろいろ探して「MFC クラスウィザード」を利用することがわかった.
今まで,よく見ていたダイアログなのに...
後は,WM_LBUTTONDOWN を処理する様にして,
void CMyListBox::OnLButtonDown(UINT nFlags, CPoint point)
{
CListBox::OnLButtonDown(nFlags, point);
int sel = GetCurSel() ;
if (sel == LB_ERR) { return ; }
CString str ;
GetText(sel,str) ;
CStringArray sa ;
sa.Add(str) ;
::StringArrayToDoDragFiles(sa) ;
}
ダイアログに追加したリスボックスで,これを利用する様にダイアログのヘッダを修正.
MSDN CTRLTEST サンプル
テクニカル ノート 14
標準コントロールからのコントロールの派生
[MSVC] MFCを使用しての動的サブクラス化
Create Client Windows, Drag and Drop Between Listboxes
2014/08/11 追記
COleDataSource を利用して,他の AP に CF_HDROP で渡そうとすると,
—————————
Microsoft Visual C++ Debug Library
—————————
Debug Assertion Failed!
Program: …Documents\Visual Studio 2010\Projects\TestVC10\Debug\T_SC.exe
File: f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\cmdtarg.cpp
Line: 43
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
—————————
中止(A) 再試行(R) 無視(I)
—————————
COleDataSource の使い方が間違っていた.
開放する時に delete ではうまくない.
データ オブジェクトとデータ ソース : 作成と破棄
モードレスダイアログの動作が,…
VC 7 以降,MDI AP のモードレスダイアログが独立して動作してしまう現象があった.
その AP は,VC 4 の頃作成したもので CMainFrame::OnCreate 内でモードレスダイアログを作成している.
VC 6 までは特に問題なかったが,VC 7 以降タスクバーにアイコンが 2 つ存在する状態になってしまっていた.
過去に何度か対応方法を調べたが,わからずそのままとなっていた.
今日別の事を調べていて,「モードレスダイアログで親子にならなくする」方法が目に留まった.
CDialog::Create で,デフォルトの NULL ではなく,GetDesktopWindow() を与えるというもの.
VC 7 AP のダイアログの情報を,Spy++ で見ると,親ウィンドウが (なし) になっている.
今度はデバッガで,Create の付近を追いかけると AfxGetMainWnd() で NULL がかえっている.
ThrdCore.cpp より
CWnd* CWinThread::GetMainWnd()
{
if (m_pActiveWnd != NULL)
return m_pActiveWnd;
if (m_pMainWnd != NULL)
return m_pMainWnd;
return CWnd::GetActiveWindow();
}
CXxxApp::InitInstance で以下の部分を修正.
CMainFrame* pMainFrame = new CMainFrame;
m_pMainWnd = pMainFrame; // ここを追加
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
return FALSE;
m_pMainWnd = pMainFrame;
CSplitterWnd – 2
SDI で,MDI の「新しいウィンドウを開く」で 4 つのビューを表示した様な動作が欲しかったので,調べてみた.
動的な分割ウィンドウである程度の所まではできそう.
1. MainFrm.h の CMainFrame に以下を追加. CSplitterWnd m_wndSplitter; virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext); 2. CMainFrame::OnCreateClient の追加. BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { { if (!m_wndSplitter.Create(this,2, 2,CSize(10, 10), pContext, WS_CHILD | WS_VISIBLE /* | WS_HSCROLL | WS_VSCROLL */ | SPLS_DYNAMIC_SPLIT)) { TRACE0("Failed to create split bar "); return FALSE; } return TRUE; } } スクロールバーを付加したくなかったので,6 つ目のウィンドウスタイルを変更している. テスト用に分割動作をコマンドとして実装. void CMainFrame::OnSplit() { if (IsSplit) { if (m_wndSplitter.GetColumnCount() > 1) { m_wndSplitter.DeleteColumn(1) ; } if (m_wndSplitter.GetRowCount() > 1) { m_wndSplitter.DeleteRow (1) ; } IsSplit = !IsSplit ; } else { CRect rect ; m_wndSplitter.GetClientRect(&rect) ; if (m_wndSplitter.GetColumnCount() == 1) { m_wndSplitter.SplitColumn(rect.Width ()/2) ; } if (m_wndSplitter.GetRowCount() == 1) { m_wndSplitter.SplitRow (rect.Height()/2) ; } IsSplit = !IsSplit ; } }
2 x 2 の分割ウィンドウのコントロールの ID (Spy++ で確認)
左上(0,0) E900 AFX_IDW_PANE_FIRST
右上(0,1) E901
左下(1,0) E910
右下(1,1) E911
ビューの OnDraw を以下の様に書き換えると
void CSpltWView::OnDraw(CDC* pDC) { int row = -1 ; int clm = -1 ; CMainFrame* mw = (CMainFrame*)AfxGetMainWnd() ; CSplitterWnd* sw = &mw->m_wndSplitter ; CString str ; if (sw->IsChildPane(this,&row,&clm)) { int id = sw->IdFromRowCol(row,clm) ; CString tmp1 ; tmp1.Format(_T("row = %d , clm = %d"),row,clm) ; CString tmp2 ; tmp2.Format(_T("IdFromRowCol = %04X"), id) ; str += tmp1 + _T("\r\n") ; str += tmp2 + _T("\r\n") ; } { UINT nID = GetDlgCtrlID() ; CString tmp ; tmp.Format(_T("GetDlgCtrlID = %04X"),nID) ; str += tmp + _T("\r\n") ; } { CWnd* pw = GetParent() ; CString tmp1 ; tmp1.Format(_T("Splitter = %08x "),sw->GetSafeHwnd()) ; CString tmp2 ; tmp2.Format(_T("Parent = %08x "),pw->GetSafeHwnd()) ; str += tmp1 + _T("\r\n") ; str += tmp2 + _T("\r\n") ; } CRect rect ; GetClientRect(rect) ; rect.top = rect.left = 10 ; pDC->DrawText(str,rect,0) ; }
MFC の ソースを眺めていると CView::GetParentSplitter があったので,間接的にはそれを使えば良さそう.
ビューでどの位置かを求めるだけなら, short texNo = 0 ; { UINT nID = GetDlgCtrlID() ; switch (nID) { case AFX_IDW_PANE_FIRST + 0x00 : texNo = 1 ; break ; case AFX_IDW_PANE_FIRST + 0x01 : texNo = 2 ; break ; case AFX_IDW_PANE_FIRST + 0x10 : texNo = 3 ; break ; case AFX_IDW_PANE_FIRST + 0x11 : texNo = 4 ; break ; } }