プログラム

2014年4月21日 (月)

Aeroが有効の環境でのウィンドウサイズ取得

Windows Vista 以降でAeroを使用している環境ではGetWindowRect()が
サイズ固定のウィンドウに対し実際のウィンドウより小さい矩形を取得してくる。
どうも、Vista以降で導入されたフレーム拡張のためらしい。

以下のサイトに感謝
http://www.orangemaker.sakura.ne.jp/labo/memo/sdk-mfc/earoframeex.html
http://jnsmith.blog64.fc2.com/blog-entry-104.html

フレーム拡張を考慮したウィンドウサイズを取得するためには
DwmGetWindowAttribute()を使用する。
Vista以降でAeroを有効としていない環境を考慮するためには
DwmGetWindowAttribute()でAaroが有効か調べる。

1.
2.
3.
4.
5.
6.
7.
BOO bAero;   
DwmGetWindowAttribute(&bAero);   
if(bAero==TRUE){   
    RECT rc;   
    DwmGetWindowAttribute(hWnd,DWMWA_EXTENDED_FRAME_BOUNDS,&rc,sizeof(rc));   
}   
‌ 
このコードは CodePublisher で生成しています

DWM関数はVista以降で用意された関数群のため
XP以前を考慮するにはDWM関数のDLLであるdwmapi.dllが
LoadLibrary()できるかで判断できる。

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
typedef HRESULT (WINAPI *PDwmIsCompositionEnabled)(BOOL*);  
typedef HRESULT (WINAPI *PDwmGetWindowAttribute)(HWND,DWORD,LPCVOID,DWORD);  
‌   
PDwmIsCompositionEnabled fpDwmIsCompositionEnabled;  
PDwmGetWindowAttribute   fpDwmGetWindowAttribute;  
‌   
TCHAR dir[MAX_PATH];  
HMODULE  hDWM;  
GetSystemDirectory(dir,sizeof(dir));  
lstrcat(dir,_T("\\dwmapi.dll"));  
hDWM=LoadLibrary(dir);  
if(hDWM!=NULL){  
    fpDwmIsCompositionEnabled=(PDwmIsCompositionEnabled)GetProcAddress(hDWM,"DwmIsCompositionEnabled");  
    fpDwmGetWindowAttribute=(PDwmGetWindowAttribute)GetProcAddress(hDWM,"DwmGetWindowAttribute");  
}  
‌  
‌ 
このコードは CodePublisher で生成しています

なお、これらDWM関数の戻り値はHRESULT型なので
関数が成功しているか調べるためにはSUCCEEDED()マクロを使用する。

| | コメント (1) | トラックバック (0)

2013年6月24日 (月)

AWKについて

ほそぼそと復活しているのは嬉しい。

AWKは個人的に好きなプログラミング言語。
AWKのKはカーニハンのKだけあってなのか?、文法はCやC系統の言語を扱える人にとって馴染みやすい。

テキスト処理に特化した言語で、何だかの規則性があるテキストを処理したい場合に強力な道具となる。
仕事柄、定型的なテキスト処理を繰り返したい場面が多い。
このような作業はめんどくさいので(ミスを減らすためにも)、できるだけ自動化したい、というときに活躍する。
使っていると、とてもシンプルな言語で、お手軽に扱える道具として追求した言語だということがわかる。
片手間で使えるようになれる程のシンプルさを持っていて、
目的を達成出来れば、作ったコードを使い捨てても惜しくないというほどお手軽に書ける。

それでいて即席で作れる数行で済むようなコードばかりが守備範囲かというとそうでもなく、
アイデア次第で柔軟なコードが書ける懐の深さも併せ持っている。
数百行以上でも、それ以上でも十分耐えられる。
そして、文法のお手軽さだけでなく、冗長的で野暮ったいコードでも気持ちが良いくらいに高速に処理してくれるのが、
ストレスフリーなお手軽さの重要なポイントだと思う。

以下の本にお世話になったがいずれも絶版になっている様子。とても惜しい。
特に、"AWKを256倍使うための本"は軽快な語り口ながらも内容が深いところまで言及してあり、
かつ、リファレンス的のもよくまとまっていて、仕事机の引き出しに入れてある。

| | コメント (0) | トラックバック (0)

2013年5月14日 (火)

SendInput()でマルチバイト文字の入力をシュミレーション

Win32 AIPによるキーボード入力のシュミレーションはSendInput()やkeybd_event()を使用する。
ひらがなや漢字などのワイド文字の生成はkeybd_event()ではなくSendInput()を使用すると楽。
この時、SendInput()に渡す文字はユニコードとする。

UINT SendInput(
  UINT nInputs,
  LPINPUT pInputs,
  int cbSize
);

INPUT構造体は以下となっている。
typeにINPUT_KEYBOARDを設定し、
KEYBDINPUを使用する。

typedef struct tagINPUT {
  DWORD         type;
  MOUSEINPUT    mi;
  KEYBDINPUT    ki;
  HARDWAREINPUT hi;
} INPUT, *PINPUT;

KEYBDINPUT構造体は以下となっている。
dwFlagsにKEYEVENTF_UNICODEを設定し、
送りたい文字はwVkではなくwScanに設定する。
dwFlagsにはDWONだけでなくUPする必要がある。

typedef struct tagKEYBDINPUT {
  WORD      wVk;
  WORD      wScan;
  DWORD     dwFlags;
  DWORD     time;
  ULONG_PTR dwExtraInfo;
} KEYBDINPUT, *PKEYBDINPUT;

ワイド文字を含んだ文字列のキーボード入力をシュミレーションする関数の例。

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
void KeyEvent(char *pinput)
{
    DWORD size;
    WCHAR *pwBuf;
    INPUT *pip;
‌ 
    pwBuf=(WCHAR*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lstrlen(pinput)*2+sizeof(WCHAR));
    if(pwBuf==NULL){
        return;
    }
‌ 
    size=MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,pinput,-1,wBuf,sizeof(wBuf));
    size-=1;
    size*=2;
‌ 
    pip=(INPUT*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size*sizeof(INPUT));
    if(pip==NULL){
        HeapFree(GetProcessHeap(),0,pwBuf);
        return;
    }
‌ 
    for(int i=0;i<size;i++){
        pip[i].type=INPUT_KEYBOARD;
        pip[i].ki.dwFlags=KEYEVENTF_UNICODE;
        pip[i].ki.wScan=pwBuf[i/2];
        if(i%2){
            pip[i].ki.dwFlags|=KEYEVENTF_KEYUP;
        }
    }
    SendInput(size,pip,sizeof(INPUT));
‌ 
    HeapFree(GetProcessHeap(),0,pip);
    HeapFree(GetProcessHeap(),0,pwBuf);
}
このコードは CodePublisher で生成しています

| | コメント (0) | トラックバック (0)

2012年10月24日 (水)

libファイルを作成する方法

VisualStudioでlibファイルを作成する方法です。
VisualStudio2010を前提としています。

defファイルがある場合はVisual Studioに付属のlib.exeを使用します。

lib /DEF:defファイル名 /OUT:libファイル名 /MACHINE:X86

/MACHINE:はターゲットプラットフォームを指定します。
通常、32bit版は"X86"、64bit版は"X64"を指定します。

MSDNのlib.exeのベージ
<http://msdn.microsoft.com/ja-jp/library/7ykb2k5f(v=vs.80).aspx>
このページの"LIB の概要"にコマンドラインオプションの説明があります。

defファイルがない場合はVisual Studioに付属のdumpbin.exeを使用しdefファイルを作成します。
dllファイルが必要です。

dumpbin /EXPORTS dllファイル名 /OUT:ファイル名

"/OUT:ファイル名"の代わりに標準出力先をファイルとしても同じ内容となります。

dumpbin /EXPORTS dllファイル名 > ファイル名

上記コマンドの出力内容の"name"の列にDLLに含まれる関数名が列挙されています。
この関数名を抜き出し、defファイルを作成します。

MSDNのdumpbin.exeのページ
<http://msdn.microsoft.com/ja-jp/library/c1h23y6c(v=vs.80).aspx>
このページの"DUMPBIN コマンド ライン"にコマンドラインオプションの説明があります。

defファイルは色々書式があるようですが、
libファイルを作成する際の最低限のフォーマットは
"EXPORTS"と記述した下にdumpbinで抽出した関数名を並べていきます。

EXPORTS
func1
func2
func3

(func*はdumpbinで抽出した関数名)

なお、lib.exeなどのVisual Studioのツールを使用する際は
スタートメニューの"Visual Studio コマンド プロンプト (2010)"、または
Visual Studioのメニュー "ツール"-"Visual Studio コマンド プロンプト"から
起動したコマンドプロンプトを使用します。
通常の方法で起動したコマンドプロンプトからlib.exeなどのツールを使用しようとしても
mspdb100.dllがないためプログラムを開始できないという旨のメッセージが表示され、
実行できません。

| | コメント (0) | トラックバック (0)

2012年8月27日 (月)

ボタンコントロールのカスタムドロー WM_NOTIFYがなぜ来ない

ボタンコントロールをカスタムドローしたくてもWM_NOTIFYが来ない。のでメモ。
ボタンコントロールの親をSpyで調べてもWM_NOTIFYが来ている様子がないし、
実際、来ていない。

MSDNのNM_CUSTOMDRAWを見たら以下のようにありました。

To use this API, you must provide a manifest specifying Comclt32.dll version 6.0. For more information on manifests, see Using Windows XP Visual Styles.

ComCtl32.dllのバージョンを6以上を指定しないといけないようです。

以前、これに気が付かずオーナードローしていたな。

| | コメント (0) | トラックバック (0)

2012年7月 9日 (月)

gdiplus.h インクルードによるコンパイルエラー

GDI+を使用するためにgdiplus.hをインクルードしますが、
<http://support.microsoft.com/kb/922323>
このページにも書いてある通り、
stdafx.h内のWIN32_LEAN_AND_MEANが原因でコンパイルエラーになります。
上記のページではVisualStudio2005とありますが、依然として2010でも同様です。
この回避方法としてWIN32_LEAN_AND_MEANを削除すれば良いのですが、
windows.hの中を見るとわかるように、
WIN32_LEAN_AND_MEAN を削除するとwinsock.hなど
場合によってはインクルードしたくないヘッダまでインクルードしてしまいます※1。
このため、WIN32_LEAN_AND_MEAN を残したままにしたい場合は、
ole2.hをgdiplus.hの前でインクルードする、
または、gdiplus.hはole2.hの中のobjbase.hが欲しいようなので、
ole2.hの代わりにobjbase.hをインクルードすることでコンパイルエラーを回避できます。

※1 この場合も、winsock2.hで #define _WINSOCKAPI_ しているため、
windows.hよりも前にwinsock2.hをインクルードすれば、
windows.hでインクルードしているwinsock.hは無効化されます。

| | コメント (0) | トラックバック (0)

2012年4月11日 (水)

Oracle認定 JavaプログラマSE6

趣味で少しばかり触った程度のJavaですが、なぜかJavaプログラマSE6を受験し、一応合格しました。

試験対策として「Oracle試験対策 JavaプログラマSE 6問題集」を使用しました。
問題集なので基本的な文法を理解していることを前提とした簡潔な解説となっていますが、
問題ひとつひとつをどういった狙いで出題しているのかが明確になっており、
目的意識を持って問題にのぞめるのがこの問題集の優れた点だと思います。
実際に試験で出題された問題と視点が似ておりよく研究されていると感じました。
Javaの基本的な文法を理解しているのなら問題集だけで合格できると思います。

読んでいないので内容の善し悪しはわかりませんが、
同じ著者の解説本もあります。

赤いほうが問題集、青いほうが解説本です。



Oracle試験対策 JavaプログラマSE 6問題集の正誤表です。
http://www.sbcr.jp/support/9921.html

| | コメント (0) | トラックバック (0)

2012年1月16日 (月)

EM_SETSEL/EM_GETSEL/EM_LIMITTEXT

エディットコントロールのメッセージである
EM_SETSEL/EM_GETSEL/EM_LIMITTEXTで気が付かなかった挙動のメモ。

Common Control 6.0を使用すると上記のメッセージはbyte数ではなく文字数で解釈されるようです。
このため、例えば、"あいうabc"という文字列は9ではなく6として扱われます。

[WinXP] Common Control 6.0 の EM_LIMITTEXT による入力制限
http://support.microsoft.com/default.aspx?scid=kb;ja;418099

| | コメント (0) | トラックバック (0)

2011年9月11日 (日)

UAC環境で管理者権限を要求する実行ファイルを作成する

Visual C++で実行時に管理者権限を要求する実行ファイルを作成する方法のメモ。

requestedExecutionLeveをrequireAdministratorとする以下のようなマニフェストを用意。
マニフェストのファイル名は[アプリケーション名].exe.manifest とし、プロジェクトのソースと同じフォルダに格納します。
マニフェストファイル内のnameのAppNameにはアプリケーション名を入れます。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
   <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="AppName" type="win32"/>
      <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
      <security>
         <requestedPrivileges>
            <requestedExecutionLevel level="requireAdministrator"/>
         </requestedPrivileges>
      </security>
   </trustInfo>
</assembly>

次にプロジェクトのプロパティからビルドイベントのビルド後イベントに以下を追加します。

mt.exe -manifest "$(ProjectDir)$(TargetName).exe.manifest" -outputresource:"$(TargetDir)$(TargetFileName)";#1

mt.exe に作成したマニフェストとマニフェストを埋め込むファイルのパスを渡します。
末尾の数字は対象ファイルがEXEの場合は1、DLL の場合は2なります。

コンパイルしてアイコンの右下に以下のようなマークが付いたら成功です。

Icon

| | コメント (0) | トラックバック (0)