☆Cソース
//Libraryの在処
//C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Lib\ComCtl32.Lib
//これを入れないとINPUT構造体が有効にならない
#define _WIN32_WINNT 0x0500
#define STRICT
#define ID_LISTVIEW 100
#define ID_MYCHILD 110
#define T_BUFFER 1024
#define COLUMN_WIDTH 120
//クリップボードから読みこむ文字列の最大サイズ
#define MAX_READCB 1024 * 64
//文字列の動的配列の際に確保する個々のサイズ
#define MALLOC_UNIT 1024
//ユーザ領域のメッセージを定義
#define WM_START_CAPTURE (WM_APP + 1)
#include "resource.h"
#include <windows.h>
#include <commctrl.h>
#include <tchar.h>
#include <string.h>
//マルチバイト→Unicodeに必要
#include <locale.h>
//IMEの名前制御用 imm32.libをプロジェクトに参加要→結局IMEの判別は64bitOSでうまくいかず断念している
#include <imm.h>
/////////////////////////////////////////////////////////////////////////////
// プロトタイプ宣言
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildProc(HWND, UINT, WPARAM, LPARAM);
BOOL InitApp(HINSTANCE, WNDPROC, LPCTSTR);
BOOL InitInstance(HINSTANCE, int, LPCTSTR);
////////////////////////////////////////////////////////
// ユーザー関数
int PasteFromCB(HWND hWnd, char *szStr, int &szSize);
int ReadClip(HWND hwnd, char *str);
//文字列の配列渡しの例(*cells)[256]の形でプロトタイプ宣言する必要がある
//実際に引数で渡すときはcellsで良い。
//int SplitTAB(char *row, char (**cells)[256], int &cellscount);
int SplitTAB(char *row, char **cells, int &cellscount);
int WriteClip(HWND hWnd, char *str);
int ReadClip(HWND, char *);
int PasteFromCB(HWND hWnd);
void KeyInput(char *,HWND);
void VKeyInput(int , int);
int myActivateWindow(HWND hWnd);
void listview_delallcoloumn(HWND hlistview);
int set_listview(HWND hWnd, HWND hlist);
HWND MakeMyList(HWND hWnd);
void ShowMyText(HWND hWnd);
//////////////////////////////////////////////////////////////
// グローバル変数
HINSTANCE hInst;
//ファイルの各行を読みこむ文字列の動的配列
char **mylist;
int mylistcount = 0;
//セル情報の動的配列
char **mycell;
int mycellcount = 0;
//マウスキャプチャー中のフラグ
BOOL bCap = FALSE;
//改行コード送信回数設定
int CRcount = 0;
bool IsEmpty = true;
HWND hXl; //エクセルのハンドル
HWND hKeep;
/////////////////////////////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst,
LPSTR lpsCmdLine, int nCmdShow)
{
MSG msg;
LPCTSTR szClassName = "listView01";
if (!hPrevInst) {
if (!InitApp(hCurInst, WndProc, szClassName))
return FALSE;
}
if (!InitInstance(hCurInst, nCmdShow, szClassName)) {
return FALSE;
}
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
/////////////////////////////////////////////////////////////////////////
//ウィンドウ・クラスの登録
BOOL InitApp(HINSTANCE hInst, WNDPROC WndProc, LPCTSTR szClassName)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "MYMENU";
wc.lpszClassName = (LPCSTR)szClassName;
return (RegisterClass(&wc));
}
/////////////////////////////////////////////////////////////////////////
//ウィンドウの生成
BOOL InitInstance(HINSTANCE hInst, int nCmdShow, LPCTSTR szClassName)
{
HWND hWnd;
hWnd = CreateWindow(szClassName,
"エクセルデータ転記",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
200,
100,
NULL,
NULL,
hInst,
NULL);
if (!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
//最前面表示
SetWindowPos(hWnd , HWND_TOPMOST ,0 , 0 , 0 , 0 ,SWP_NOMOVE | SWP_NOSIZE );
return TRUE;
}
/////////////////////////////////////////////////////////////////////////
//ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
static HWND hList;
static HWND hChdWnd;
HINSTANCE hInst;
LV_ITEM item;//リストビューのアイテム設定用
LV_HITTESTINFO lvhti;//HITTEST設定用
LV_DISPINFO *lvinfo;
char buf[T_BUFFER];
static HWND hEdit;
//カスタムドロー(一行おきに行の着色)
//LPNMLISTVIEW lplv;
LPNMLVCUSTOMDRAW lplvcd;
static HFONT hCustomFont, hOrgFont;
//マウスキャプチャー中かのフラグ
static bool captureFlag;
int ret;
//かな漢字変換情報取得用 - 結局使っていません
HKL hKl;
char szName[1024];
//IMEの名前比較用
char *sp;
switch (msg) {
case WM_CREATE:
//エクセルのハンドル取得
//ここで取得できなかったとき、いつ取得するかという問題があるので
//エクセルのハンドルが取得できなければ終了する様にしてある
hXl = FindWindow(TEXT("XLMAIN"),NULL);
if (hXl == NULL){
MessageBox(hXl, "エクセルが起動されていません", "OK", MB_OK);
DestroyWindow(hWnd);
break;
}
hKeep = hXl; // エクセルのハンドルを保存
hInst = ((LPCREATESTRUCT)lp)->hInstance;
InitApp(hInst,
ChildProc,
"child");
hChdWnd = CreateWindow("child",
"他アプリのハンドル取得",//タイトルバーにこの名前が表示されます
WS_CHILD | WS_SYSMENU | WS_THICKFRAME | WS_CAPTION , //ウィンドウの種類
CW_USEDEFAULT, //X座標
CW_USEDEFAULT, //Y座標
200, //幅
100, //高さ
hWnd, //親ウィンドウのハンドル、親を作るときはNULL
(HMENU)ID_MYCHILD, //メニューハンドル、子供のID
hInst, //インスタンスハンドル
NULL);
ShowWindow(hChdWnd, SW_HIDE);
UpdateWindow(hChdWnd);
SetWindowPos(hChdWnd , HWND_TOPMOST ,0 , 0 , 0 , 0 ,SWP_NOMOVE | SWP_NOSIZE );
SetCursor(LoadCursor(NULL, IDC_ARROW));
//メニューの操作
CRcount = 0;
EnableMenuItem(GetMenu(hWnd), ID_CR1, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), ID_CR2, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), ID_CR0, MF_GRAYED);
InvalidateRect(hWnd, NULL, TRUE);
/*
//IMEがATOKか否か調査 - 64bitOSでうまくいかないので没
ret = GetWindowThreadProcessId(hXl,NULL);
if (ret == 0) MessageBox(hXl, "ProcessID取得失敗", "OK", MB_OK);
long long ret2;
hKl = GetKeyboardLayout(GetWindowThreadProcessId(hXl,NULL));
if (!ImmIsIME(hKl)) {
MessageBox(hXl, "IMEを持っていません", "OK", MB_OK);
return FALSE;
}
ImmGetDescription(hKl, szName, 64);
//ATOK または Microsoft IME standard
MessageBox(hWnd, szName, "IMEの種類", MB_OK);
sp = strstr(szName,"ATOK");
if (sp != NULL)
{
IsATOK = true;
MessageBox(hWnd, "IMEはATOKです", "IMEの種類", MB_OK);
}else{
IsATOK = false;
}
*/
InitCommonControls();
hList = MakeMyList(hWnd);
//文字列の動的配列の初期化 100個分を確保
mylist=(char**)malloc(sizeof(char*) * 100);
mylistcount = 100;
//クリップボードから文字列を読みこみ、改行とTABでSplitしてlistviewに設定
ret = set_listview(hWnd, hList);
break;
case WM_COMMAND:
switch (LOWORD(wp)) {
//改行送信の有無切り替え
case ID_CR0:
CRcount = 0;//IsCRLF = false;
EnableMenuItem(GetMenu(hWnd), ID_CR1, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), ID_CR2, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), ID_CR0, MF_GRAYED);
InvalidateRect(hWnd, NULL, TRUE);
break;
case ID_CR1:
CRcount = 1;//IsCRLF = false;
EnableMenuItem(GetMenu(hWnd), ID_CR0, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), ID_CR2, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), ID_CR1, MF_GRAYED);
InvalidateRect(hWnd, NULL, TRUE);
break;
case ID_CR2:
CRcount = 2;//IsCRLF = false;
EnableMenuItem(GetMenu(hWnd), ID_CR0, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), ID_CR1, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), ID_CR2, MF_GRAYED);
InvalidateRect(hWnd, NULL, TRUE);
break;
case IDM_XL:
MessageBox(hWnd, "貼付先をエクセルに戻します", "Excel", MB_OK);
hXl = hKeep;
break;
case IDM_END:
SendMessage(hWnd, WM_CLOSE, 0, 0);
break;
//クリップボードから再取得
case IDM_DEL:
//全アイテムを消す
ListView_DeleteAllItems(hList);
//カラムを全て削除。全アイテム削除と一緒に使わないとゴミが残るらしい
listview_delallcoloumn(hList);
//クリップボードから文字列を読みこみ、改行とTABでSplitしてlistviewに設定
ret = set_listview(hWnd,hList);
break;
//子ウィンドウを表示し、マウスキャプチャーで他アプリのハンドル取得
case IDM_HWD:
ShowWindow(hChdWnd, SW_SHOW);
SendMessage(hChdWnd,WM_START_CAPTURE,0,0);
break;
}
break;
case WM_NOTIFY:
if ((int)wp == ID_LISTVIEW) {
lvinfo = (LV_DISPINFO *)lp;
switch (lvinfo->hdr.code) {
//http://bu-nyan.m.to/sdk/sdk18.htm
case NM_DBLCLK://項目をダブルクリックしたときに!NM_DBLCLK
//マウスカーソルの座標を取得します。
GetCursorPos((LPPOINT)&lvhti.pt);
//ScreenToClient(((LPNMLISTVIEW)lP)->hdr.hwndFrom, &lvhti.pt);
ScreenToClient(lvinfo->hdr.hwndFrom ,&lvhti.pt);
//ListView_HitTest(((LPNMLISTVIEW)lP)->hdr.hwndFrom, &lvhti);
//マウスカーソルがリストビューの項目上にあるかどうかを判定します。
//サブアイテムも取得したいときは、下記を使う
ListView_SubItemHitTest(lvinfo->hdr.hwndFrom, &lvhti);
if (lvhti.flags & LVHT_ONITEM){
item.mask = TVIF_HANDLE | TVIF_TEXT;
item.iItem = lvhti.iItem;//取得アイテムの番号
item.iSubItem = lvhti.iSubItem;
item.pszText=buf;//格納するテキストバッファ
item.cchTextMax=T_BUFFER;//バッファ容量
ListView_GetItem(lvinfo->hdr.hwndFrom, &item);
WriteClip(hWnd, buf);
//エクセルをアクティブにする
myActivateWindow(hXl);
//エクセルに選択されたデータとRETURNを送る
//複数のエクセルが開いているときは?未検証。
//今回動作しているが、1文字ずつ送って、間にSleepを入れないと取りこぼすという記事あり
KeyInput(buf,hWnd);
for (int i = 0; i < CRcount; i++){
Sleep(50);
VKeyInput(VK_RETURN , 1);
}
}
break;
case NM_CUSTOMDRAW :
// カスタムドローで、Listviewの色を設定。
//http://www.kumei.ne.jp/c_lang/sdk3/sdk_261.htm
lplvcd = (LPNMLVCUSTOMDRAW)lp;
if (lplvcd->nmcd.dwDrawStage == CDDS_PREPAINT)
return CDRF_NOTIFYITEMDRAW;
if (lplvcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) {
if (lplvcd->nmcd.dwItemSpec % 2){
SelectObject(lplvcd->nmcd.hdc, hCustomFont);
lplvcd->clrTextBk = RGB(204, 255, 204);
lplvcd->clrText = RGB(0, 0, 102);
return CDRF_NEWFONT;
}
}
break;
}
}
break;
case WM_SIZE:
MoveWindow(hList, 0, 0, LOWORD(lp), HIWORD(lp), TRUE);
break;
case WM_CLOSE:
//id = MessageBox(hWnd,
// "終了してもよいですか",
// "終了確認",
// MB_YESNO | MB_ICONQUESTION);
//if (id == IDYES) {
// DestroyWindow(hWnd);
//}
if (IsEmpty != true)
{
//文字列の動的配列用に確保したメモリの解放
for ( int i = 0; i < mylistcount; i++)
free(mylist[i]);
free(mylist);
}
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, msg, wp, lp));
}
return 0L;
}
//listviewに追加する箇所の統一化
int set_listview(HWND hWnd, HWND hList)
{
LV_COLUMN lvcol;//リストビューのカラム設定用
LV_ITEM item;//リストビューのアイテム設定用
RECT rcf;
RECT rcc;
SIZE fsize;
//クリップボードから読みこんだ文字列を収納する配列
char szStr[MAX_READCB];
//同配列に納められたデータ数
int szSize;
int cellcount; //一行のセル数
int ret;
int totalColumnWidth = 0;
int maxTotalColWidth = 0;
char buf[T_BUFFER];
//クリップボードから読み出し
ret = PasteFromCB(hWnd , szStr, szSize);
if (ret != 0 ) return 0;
else IsEmpty = false;
//セルの個数を取得
//クリップボード空からの再読込でアクセス違反発生
//mycellcount=0のため追加->Debugモードだと、各変数の値が確認できる
mycell = (char**)malloc(sizeof(char*) * 100);
mycellcount = 100;
ret = SplitTAB( mylist[0], mycell, cellcount);
for ( int i = 0; i < mycellcount; i++)
free(mycell[i]);
free(mycell);
//見出しの生成
lvcol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvcol.fmt = LVCFMT_LEFT;
for (int i = 0; i <= cellcount; i++){
lvcol.cx = COLUMN_WIDTH;
wsprintf( buf, "F%d", i + 1 );
lvcol.pszText = buf;
lvcol.iSubItem = i;
ListView_InsertColumn(hList, i, &lvcol);
}
item.mask = LVIF_TEXT;
//リストビューに追加
for (int i = 0; i <= szSize; i++){
mycell = (char**)malloc(sizeof(char*) * 100);
mycellcount = 100;
ret = SplitTAB( mylist[i], mycell, cellcount);
//タブ区切り文字列の個数だけ繰り返し
for (int j = 0; j <=cellcount; j++){
item.pszText = mycell[j];
if (j == 0){
item.iItem = i;
item.iSubItem = 0;
ListView_InsertItem(hList, &item);
}
else{
//SubItem
item.iItem = i;
item.iSubItem = j;
ListView_SetItem(hList, &item);
}
}
for ( int i = 0; i < mycellcount; i++) free(mycell[i]);
free(mycell);
//列幅の自動設定
totalColumnWidth = 0;
for (int i = 0; i <= cellcount; i++){
ListView_SetColumnWidth(hList, i, LVSCW_AUTOSIZE) ;
totalColumnWidth = totalColumnWidth + ListView_GetColumnWidth(hList, i);
}
if (maxTotalColWidth < totalColumnWidth )
maxTotalColWidth = totalColumnWidth;
}
//読みこんだ列数、行数に合わせてフォームのサイズを変更
GetWindowRect(hWnd, (LPRECT)&rcf);
GetClientRect(hWnd, (LPRECT)&rcc);
//Windowの枠サイズ取得
fsize.cx = (rcf.bottom - rcf.top) - (rcc.bottom - rcc.top );
fsize.cy = (rcf.right - rcf.left ) - (rcc.right - rcc.left );
//zオーダーを変更しないオプションを指定してみた
SetWindowPos(hWnd , HWND_TOP ,0 , 0 , maxTotalColWidth + fsize.cx , (szSize + 1) * 18 + fsize.cy + 38 ,SWP_NOMOVE | SWP_NOZORDER );
return 0;
}
//リストビューのカラムを全て消す
//http://bluefish.orz.hm/sdoc/winprog_memo.html#リストビューの削除
void listview_delallcoloumn(HWND hlistview)
{
int i,count;
//カラム数を求める
count = Header_GetItemCount(ListView_GetHeader(hlistview));
for (i=0; i<count ;i++) {
ListView_DeleteColumn(hlistview,0);
}
}
//文字列をタブ区切り分解して文字列配列に収納して戻す
//int SplitTAB(char *row, char (*cells)[256], int &cellscount)
int SplitTAB(char *row, char **cells, int &cellscount)
{
DWORD dwAccBytes;
dwAccBytes = strlen(row);
//一行の文字列を読みこむバッファ
char buf[MALLOC_UNIT];
int j = 0;
int k = 0;
for (int i = 0; i < (dwAccBytes ); i++)
{
buf[j] = row[i];
j++;
//先頭に結合セルがあるとき最初の文字がTABになるため配置が崩れる対策
if (row[i] == 0x09){
if (i > 0) {
buf[j - 1] = 0;
}
else{
buf[0]=0;
}
mycell[k] = (char*)calloc(MALLOC_UNIT,sizeof(char));
strcpy_s(mycell[k],MALLOC_UNIT,buf);
k++;
if(k >= mycellcount){
mycellcount = mycellcount + 100;
mycell = (char**)realloc(mycell, sizeof(char*) * mycellcount);
}
j = 0;
}
}
buf[j] = 0;
mycell[k] = (char*)calloc(MALLOC_UNIT,sizeof(char));
strcpy_s(mycell[k],MALLOC_UNIT,buf);
mycellcount = k + 1;
cellscount = k;
return 0;
}
//クリップボードから文字列を読みこみ、CRLFで行毎に分離し、
//グローバル宣言した文字列の配列mylist[]に書き込む
int PasteFromCB(HWND hWnd , char *szStr, int &szSize)
{
DWORD dwAccBytes;
char *szTitle_org = TEXT("テキスト一行転送");
//一行の文字列を読みこむバッファ
char buf[MAX_READCB];
int ret;
ret = ReadClip(hWnd, szStr);
if (ret != 0) return -1;
dwAccBytes = strlen(szStr);
int j = 0;
int k = 0;
for (int i = 0; i < (dwAccBytes ); i++)
{
buf[j] = szStr[i];
j++;
//最初の文字でなく、0x0aすなわち\nであるとき
//最後の行は出力されない。EOFであって、改行コードが無い。
if ((i > 0) && (szStr[i] == 0x0a)){
if( szStr[i - 1] == 0x0d){
buf[j - 2] = 0;
//MessageBox(hWnd, buf, TEXT("モニタ"),MB_OK);
mylist[k]=(char*)calloc(MALLOC_UNIT,sizeof(char));
strcpy_s(mylist[k],MALLOC_UNIT,buf);
//strcpy(mylist[k], buf);
//strcpy_s(mylist[k], _countof(mylist[k]), buf);
k++;
//確保した配列サイズを超過する時は拡張
if (k >= mylistcount){
mylistcount = mylistcount + 100;
mylist = (char**)realloc(mylist, sizeof(char*) * mylistcount);
}
j = 0;
}
}
}
buf[j] = 0;
mylist[k] = (char*)calloc(MALLOC_UNIT, sizeof(char));
strcpy_s(mylist[k],MALLOC_UNIT,buf);
//freeの際に使用するためリザーブ
mylistcount = k + 1;
szSize = k;
return 0;
}
//クリップボードからテキスト形式データ取得
int ReadClip(HWND hwnd, char *str)
{
HGLOBAL hGlobal;
LPSTR lpStr;
int iLength, i;
if(!IsClipboardFormatAvailable(CF_TEXT)) {
MessageBox(hwnd, "クリップボードにテキストがありません", "Message", MB_OK);
return -1;
}
OpenClipboard(hwnd);
hGlobal = (HGLOBAL)GetClipboardData(CF_TEXT);
if (hGlobal == NULL) {
CloseClipboard();
return -2;
}
lpStr = (LPSTR)GlobalLock(hGlobal);
iLength = lstrlen(lpStr) + 1;
if (iLength > MAX_READCB)
iLength = MAX_READCB;
for (i = 0; i < iLength; i++)
str[i] = lpStr[i];
GlobalUnlock(hGlobal);
CloseClipboard();
InvalidateRect(hwnd, NULL, TRUE);
return 0;
}
//Clipboardにテキスト書き込み
int WriteClip(HWND hwnd, char *str)
{
HGLOBAL hGlobal;
int iLength;
LPSTR lpStr;
int i;
iLength = lstrlen(str);
if (iLength > 1024)
iLength = 1024;
hGlobal = GlobalAlloc(GHND, iLength + 1);
if (hGlobal == NULL)
return -1;
lpStr = (LPSTR)GlobalLock(hGlobal);
for (i = 0; i < iLength; i++)
*lpStr++ = *str++;
GlobalUnlock(hGlobal);
if (OpenClipboard(hwnd) == 0) {
GlobalFree(hGlobal);
return -2;
}
EmptyClipboard();
SetClipboardData(CF_TEXT, hGlobal);
CloseClipboard();
return 0;
}
//SendKeys代替APIを使用するための関数
//適宜sleepを入れないと誤動作することがあるらしい
//http://blogs.wankuma.com/youchi/archive/2010/07/26/191637.aspx
//Vectorを使用しない様に改造してみた
// マルチバイト文字用(CP_ACP固定w)
void KeyInput( char *Text_ ,HWND hWnd)
{
//変換文字列格納バッファ
WCHAR wStrW[MALLOC_UNIT * 2];
size_t wLen = 0;
errno_t err = 0;
INPUT *myinputs;
//ロケール指定
setlocale(LC_ALL,"japanese");
//変換
err = mbstowcs_s(&wLen, wStrW, MALLOC_UNIT, Text_, _TRUNCATE);
//MessageBoxW(hWnd, wStrW, (LPCWSTR)TEXT("モニタ"),MB_OK);
//std::vector<INPUT> inputs;
myinputs = (INPUT *)malloc(sizeof(INPUT) * wLen * 2);
for( int i = 0; i < wLen; i++ )
{
for( int j = 0; j < 2; j++ )
{
INPUT input;
input.type = INPUT_KEYBOARD;
input.ki.wVk = 0;
input.ki.wScan = wStrW[ i ];
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
input.ki.dwFlags = KEYEVENTF_UNICODE;
if( j != 0 )
{
input.ki.dwFlags |= KEYEVENTF_KEYUP;
}
//inputs.push_back( input );
myinputs[i * 2 + j] = input;
}
}
//SendInput( wLen * 2, &inputs[ 0 ], sizeof( INPUT ) );
SendInput( wLen * 2, myinputs, sizeof( INPUT ) );
free(myinputs);
return;
}
// VK_xxx 用
void VKeyInput( int VKeys_, int Count_ )
{
//std::vector<INPUT> inputs;
INPUT *myinputs;
myinputs = (INPUT *)malloc(sizeof(INPUT) * Count_ * 2);
for( int i = 0; i < Count_; i++, VKeys_++ )
{
for( int j = 0; j < 2; j++ )
{
INPUT input;
input.type = INPUT_KEYBOARD;
input.ki.wVk = VKeys_;
input.ki.wScan = ::MapVirtualKey( VKeys_, 0 );
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
input.ki.dwFlags = KEYEVENTF_SCANCODE;
if( j != 0 )
{
input.ki.dwFlags |= KEYEVENTF_KEYUP;
}
//inputs.push_back( input );
myinputs[i * 2 + j] = input;
}
}
//::SendInput( Count_ * 2, &inputs[ 0 ], sizeof( INPUT ) );
SendInput( Count_ * 2, myinputs, sizeof( INPUT ) );
free(myinputs);
return;
}
//指定ウィンドウ(他アプリ)をアクティブにしてSendInputの前準備
int myActivateWindow(HWND hWnd)
{
int lngThreadTop;
int lngThreadMe;
int lngResult;
int lngResult2;
HWND lngHandle;
//現在のアクティブのWindowハンドルを取得
lngHandle = GetForegroundWindow();
//現在のアクティブWindowのスレッドIDを取得
if (lngHandle)
lngThreadTop = GetWindowThreadProcessId(lngHandle,0);
//アクティブにしようとしているWindowハンドルのスレッドを取得
if (lngThreadTop)
lngThreadMe = GetWindowThreadProcessId(hWnd,0);
//スレッドをアタッチする
if (lngThreadMe)
lngResult = AttachThreadInput(lngThreadMe, lngThreadTop, 1);
//隠れている場合手前に表示する
if (lngResult)
lngResult = BringWindowToTop(hWnd);
//アクティブ(フォアグラウンド)にする
if (lngResult)
lngResult2 = SetForegroundWindow(hWnd);
//スレッドをデタッチする
if (lngResult2)
lngResult = AttachThreadInput(lngThreadMe, lngThreadTop, 0);
return lngResult;
}
//リストビューを作成。リストビューのハンドルを戻す。
//拡張設定を行っている。
//http://www.kumei.ne.jp/c_lang/sdk2/sdk_198.htm
HWND MakeMyList(HWND hWnd)
{
HWND hList;
DWORD dwStyle;
hList = CreateWindowEx(0,
WC_LISTVIEW, "",
WS_CHILD | WS_VISIBLE | LVS_REPORT | WS_CLIPSIBLINGS,
0, 0, 0, 0,
hWnd,
(HMENU)ID_LISTVIEW,
hInst,
NULL);
dwStyle = ListView_GetExtendedListViewStyle(hList);
//dwStyle |= LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT |
// LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP;
dwStyle |= LVS_EX_GRIDLINES;
ListView_SetExtendedListViewStyle(hList, dwStyle);
return hList;
}
LRESULT CALLBACK ChildProc(HWND hChdWnd, UINT msg, WPARAM wp, LPARAM lp)
{
//int id;
POINTS pts;
POINT pt;
HWND hTarget;
HWND hWnd;
HWND hRoot;
char appliname[256];
hWnd = GetParent(hChdWnd);
switch (msg) {
case WM_START_CAPTURE:
//MessageBox(hChdWnd,"子ウィンドウから目的アプリにドラッグしてください","他アプリのハンドル取得",MB_OK);
break;
case WM_LBUTTONDOWN:
bCap = TRUE;
SetCapture(hChdWnd);
pts = MAKEPOINTS(lp);
break;
case WM_MOUSEMOVE:
if (bCap) {
SetCursor(LoadCursor(NULL, IDC_CROSS));
pts = MAKEPOINTS(lp);
} else
SetCursor(LoadCursor(NULL, IDC_ARROW));
break;
case WM_LBUTTONUP:
if (bCap)
{
SetCursor(LoadCursor(NULL, IDC_ARROW));
pts = MAKEPOINTS(lp);
pt.x = pts.x;
pt.y = pts.y;
ClientToScreen(hWnd, &pt);
hTarget = WindowFromPoint(pt);
if (hTarget == NULL) {
MessageBox(hWnd, "失敗です", "失敗", MB_OK);
return (DefWindowProc(hWnd, msg, wp, lp));
}
hRoot = GetAncestor(hTarget,GA_ROOT);
hXl = hRoot;
GetWindowText(hRoot,(LPSTR)appliname,256);
MessageBox(hWnd, appliname, "ハンドル取得", MB_OK);
ReleaseCapture();
bCap = FALSE;
ShowWindow(hChdWnd, SW_HIDE);
}
break;
case WM_PAINT:
ShowMyText(hChdWnd);
break;
//CLOSEはやめて隠すだけとした
case WM_CLOSE:
ShowWindow(hChdWnd, SW_HIDE);
break;
default:
return (DefWindowProc(hChdWnd, msg, wp, lp));
}
return 0L;
}
//ウィンドウにテキストを表示する
void ShowMyText(HWND hWnd)
{
HDC hdc;
//char *str_org = "left=%d top=%d right=%d bottom=%d";
//char strx[256];
PAINTSTRUCT paint;
RECT rt;
LPCSTR str = "ここから目的アプリに\n"
"ドラッグして下さい";
GetClientRect(hWnd, &rt);
/*wsprintf((LPSTR)strx, (LPCSTR)str_org, rt.left, rt.top, rt.right, rt.bottom);
rt.top += 40;
rt.bottom -= 40;
rt.right -= 40;
rt.left += 40;*/
hdc = BeginPaint(hWnd, &paint);
SetTextColor(hdc, RGB(0, 0, 255));
DrawText(hdc, str, -1, &rt, DT_WORDBREAK);
EndPaint(hWnd, &paint);
return;
}
☆ヘッダーファイル
// Microsoft Visual C++ generated include file.
// Used by listvew_dat1a.rc
//
#define IDM_END 101
#define IDM_INSCOLUMN 102
#define IDM_INSITEM 103
#define IDM_SETSUB 104
#define IDI_ICON1 104
#define IDM_DEL 105
#define IDM_HWD 40002
#define IDM_XL 40003
#define ID_CR0 40004
#define ID_CR1 40005
#define ID_CR2 40006
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 105
#define _APS_NEXT_COMMAND_VALUE 40003
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
☆リソースファイル
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Generated from the TEXTINCLUDE 2 resource.
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// 日本語 resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
#ifdef _WIN32
LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
#pragma code_page(932)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
// TEXTINCLUDE
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
// Menu
MYMENU MENU
BEGIN
POPUP "ファイル(&F)"
BEGIN
MENUITEM "終了(&X)", IDM_END
END
MENUITEM "更新(&R)", IDM_DEL
POPUP "切替(&H)"
BEGIN
MENUITEM "変更(&A)", IDM_HWD
MENUITEM "戻す(&X)", IDM_XL
END
POPUP "改行(&E)"
BEGIN
MENUITEM "0(&0)", ID_CR0
MENUITEM "1-ATOK(&1)", ID_CR1
MENUITEM "2-MSIME(&2)", ID_CR2
END
END
/////////////////////////////////////////////////////////////////////////////
// Icon
IDI_ICON1 ICON "271.ico"
#endif // 日本語 resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
#endif // not APSTUDIO_INVOKED