ホーム » 2015 (ページ 3)
年別アーカイブ: 2015
コンソール 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 などを使うことは,やめ.
コンテキストメニューが表示されない
あるダイアログベースの exe をテストしていて,右クリックでメニューが表示されない現象となった.
ボタンによる動作のメニューは表示される.
デバッガで追いかけると,次の様なコードの CMenu::LoadMenu が FALSE となっていた.
void CXxxxDlg::PopupSingleSel(CPoint pt,CWnd *wnd)
{
CMenu menu ;
if (!menu.LoadMenu(IDR_SINGL_SEL)) { return ; }
CMenu* pPopup = menu.GetSubMenu(0);
…
}
ボタンによるメニュー表示は次のコード.
void CXxxxDlg::OnOther()
{
CMenu menu ;
if (!menu.LoadMenu(IDR_OTHER)) { return ; }
CMenu* pPopup = menu.GetSubMenu(0);
…
}
double -> long
double の値を long にキャストした時,VC 8 で思った動作ではなかったので調べてみた.
テストに使用したのは次の様な単純なコード.
// T_DtoI.cpp
#include <iostream>
int main(int argc, char* argv[])
{
double d8 = 1/7. ;
for (int index=0 ; index<25 ; index++) {
d8 = (d8 * 7) ;
__int64 i8 = __int64(d8) ;
long l4 = long(d8) ;
printf ((“%15g\t%25I64d\t%20I64x\t%15ld\t%15x\n”),d8,i8,i8,l4,l4) ;
}
return 0;
}
d8 の値を /7 と *7 としているのはあまり意味はない.
C:\Users\Iwao>\\DevXP\C_Drive\Temp\TestCPP\T_DtoI\Release.060\T_DtoI.exe 1 1 1 1 1 7 7 7 7 7 49 49 31 49 31 343 343 157 343 157 2401 2401 961 2401 961 16807 16807 41a7 16807 41a7 117649 117649 1cb91 117649 1cb91 823543 823543 c90f7 823543 c90f7 5.7648e+006 5764801 57f6c1 5764801 57f6c1 4.03536e+007 40353607 267bf47 40353607 267bf47 2.82475e+008 282475249 10d63af1 282475249 10d63af1 1.97733e+009 1977326743 75db9c97 1977326743 75db9c97 1.38413e+010 13841287201 339014821 956385313 39014821 9.6889e+010 96889010407 168f08f8e7 -1895237401 8f08f8e7 6.78223e+011 678223072849 9de93ece51 -381759919 e93ece51 4.74756e+012 4747561509943 45160b7a437 1622647863 60b7a437 3.32329e+013 33232930569601 1e39a5057d81 -1526366847 a5057d81 2.32631e+014 232630513987207 d39383266e87 -2094633337 83266e87 1.62841e+015 1628413597910449 5c908960d05b1 -1777531471 960d05b1 1.13989e+016 11398895185373144 287f3c1a5b27d8 442181592 1a5b27d8 7.97923e+016 79792266297612000 11b7aa4b87e16e0 -1199696160 b87e16e0 5.58546e+017 558545864083283968 7c05a810b72a000 192061440 b72a000 3.90982e+018 3909821048582987776 3642798750226000 1344430080 50226000 2.73687e+019 -9223372036854775808 8000000000000000 0 0 1.91581e+020 -9223372036854775808 8000000000000000 0 0 C:\Users\Iwao>\\DevXP\C_Drive\Temp\TestCPP\T_DtoI\Release.080\T_DtoI.exe 1 1 1 1 1 7 7 7 7 7 49 49 31 49 31 343 343 157 343 157 2401 2401 961 2401 961 16807 16807 41a7 16807 41a7 117649 117649 1cb91 117649 1cb91 823543 823543 c90f7 823543 c90f7 5.7648e+006 5764801 57f6c1 5764801 57f6c1 4.03536e+007 40353607 267bf47 40353607 267bf47 2.82475e+008 282475249 10d63af1 282475249 10d63af1 1.97733e+009 1977326743 75db9c97 1977326743 75db9c97 1.38413e+010 13841287201 339014821 -2147483648 80000000 9.6889e+010 96889010407 168f08f8e7 -2147483648 80000000 6.78223e+011 678223072849 9de93ece51 -2147483648 80000000 4.74756e+012 4747561509943 45160b7a437 -2147483648 80000000 3.32329e+013 33232930569601 1e39a5057d81 -2147483648 80000000 2.32631e+014 232630513987207 d39383266e87 -2147483648 80000000 1.62841e+015 1628413597910449 5c908960d05b1 -2147483648 80000000 1.13989e+016 11398895185373144 287f3c1a5b27d8 -2147483648 80000000 7.97923e+016 79792266297612000 11b7aa4b87e16e0 -2147483648 80000000 5.58546e+017 558545864083283968 7c05a810b72a000 -2147483648 80000000 3.90982e+018 3909821048582987776 3642798750226000 -2147483648 80000000 2.73687e+019 -9223372036854775808 8000000000000000 -2147483648 80000000 1.91581e+020 -9223372036854775808 8000000000000000 -2147483648 80000000
VC 7 , 7.1 は VC 6 と同等.VC 12 までは VC 8 と同等.
Mac 64 ビットでは,long が 64 ビットのため?そのままだと VC 6 と同等になる.
long を int として 32 ビットとすると VC 8 と同等.
ここまでは,long の範囲を超えたためと理解できるが,unsigned long の場合はまた動作が異なる.
long l4 = long(d8) ;
ULONG u4 = ULONG(d8) ;
printf ((“%15g %25I64d %20I64x %12ld %10x %12ld %10x\n”),d8,i8,i8,l4,l4,u4,u4) ;
今回表面化したバグは,次のコード.
long now_Tick = long(GetTickCount_s()*1000) ;
得た値を覚えておき,次のタイミングで 1 秒以上の開きがあるかを計測したかった.
最初の頃はわからなかったが,
先日 25 日(0x7FFFFFFF 2,147,483,647)を過ぎて 0x80000000 となってしまっていた.
MSDN 浮動小数点型からの変換
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 秒程度に.