일반적으로 서로 다른 프로그램에서 Message전송만을 통한 Cotrol의 값의 복사가 가능하다. 하지만, 기본컨트롤이 아닌 다른 Cotrol에서 내용을 얻어오고자 할때는 Message와 VirtualAlloc을 이용해야 한다.
기본적인 순서는 다음과 같다.
1. 윈도우 핸들을 얻는다.
2. 차일드 윈도우목록에서 ListView의 핸들을 얻는다.
3. 메세지를 통해서 Item의 숫자를 얻는다.
4. ListView의 프로세스 id를 얻는다.
5. ListView의 프로세스에서 메모리를 할당한다.
6. 할당된 메모리와 Message를 이용하여 Item의 내용을 읽어온다.
7. 할당된 메모리를 해제
다음의 예제는 어느 회사의 사용자를 검색하여 List에 출력하여 주는 간단한 델파일 프로그램을 후킹하여 사용자정보를 CSV파일로 저장하는 루틴이다.
리스트에 표현되는 정보는 순번,이름,직책,부서명,회사명,보직/담당업무,전화번호,핸드폰,이메일 이며 EnumChildWindows는 CallBack함수를 필요로한다.
HWND hFlatEdit;
HWND hListView;
CString filename;
int lineCount = 1;
BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lPara){
HWND hEdit = ::FindWindowEx(hwnd,NULL, “TFlatEdit”,””);
HWND hList = ::FindWindowEx(hwnd,NULL, “TListView”, “”);
if(hList > 0){
hListView = hList;
//TRACE1(“List Handle : %d\n”, hList);
}
if(hEdit > 0){
//TRACE1(“Edit Handle : %d\n”,hEdit);
hFlatEdit = hEdit;
}
return TRUE;
}
void Save()
{
HWND hwnd = ::FindWindow(NULL,”사용자검색”);
CWnd* cwnd = CWnd::FromHandle(hwnd);
HINSTANCE hInstance = (HINSTANCE)(::GetWindowLong(hwnd, GWL_HINSTANCE));
if(cwnd == NULL || hInstance==0){
MessageBox(“사용자 검색창을 열어주세요”,”사용자검색창”,MB_OK);
} else {
cwnd->SetForegroundWindow();
::EnumChildWindows(cwnd->GetSafeHwnd(), EnumChildProc,LPARAM(cwnd));
int count=(int)::SendMessage(hListView, LVM_GETITEMCOUNT, 0, 0);
int i;
LVITEM lvi, *_lvi;
char item[512], subitem1[512],subitem2[512],subitem3[512],subitem4[512],subitem5[512],subitem6[512],subitem7[512],subitem8[512];
char *_item, *_subitem1,*_subitem2,*_subitem3,*_subitem4,*_subitem5,*_subitem6,*_subitem7,*_subitem8;
unsigned long pid;
HANDLE process;
GetWindowThreadProcessId(hListView, &pid);
process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|
PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, pid);
_lvi=(LVITEM*)VirtualAllocEx(process, NULL, sizeof(LVITEM),
MEM_COMMIT, PAGE_READWRITE);
_item=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
PAGE_READWRITE);
_subitem1=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
PAGE_READWRITE);
_subitem2=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
PAGE_READWRITE);
_subitem3=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
PAGE_READWRITE);
_subitem4=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
PAGE_READWRITE);
_subitem5=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
PAGE_READWRITE);
_subitem6=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
PAGE_READWRITE);
_subitem7=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
PAGE_READWRITE);
_subitem8=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
PAGE_READWRITE);
lvi.cchTextMax=512;
CFileDialog fileOpen(FALSE, “CSV저장”,NULL,OFN_HIDEREADONLY,”CSV파일 (*.csv)|*.csv|”,cwnd);
if(filename.GetLength() > 0 || fileOpen.DoModal() == IDOK){
CString mode = “”;
bool header = false;
if(filename.GetLength() == 0){
mode =”wt”;
filename = fileOpen.GetPathName();
header = true;
} else {
mode =”a”;
}
FILE * out = fopen(filename,mode);
if(header == true){
fprintf(out, “\”순번\”,\”이름\”,\”직책\”,\”부서명\”,\”회사명\”,\”보직/담당업무\”,\”전화번호\”,\”핸드폰\”,\”이메일\”\n”);
}
for(i=0; i<count; i++) {
lvi.iSubItem=0;
lvi.pszText=_item;
::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
lvi.iSubItem=1;
lvi.pszText=_subitem1;
::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
lvi.iSubItem=2;
lvi.pszText=_subitem2;
::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
lvi.iSubItem=3;
lvi.pszText=_subitem3;
::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
lvi.iSubItem=4;
lvi.pszText=_subitem4;
::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
lvi.iSubItem=5;
lvi.pszText=_subitem5;
::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
lvi.iSubItem=6;
lvi.pszText=_subitem6;
::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
lvi.iSubItem=7;
lvi.pszText=_subitem7;
::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
//lvi.iSubItem=8;
//lvi.pszText=_subitem8;
//::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
//::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
::ReadProcessMemory(process, _item, item, 512, NULL);
::ReadProcessMemory(process, _subitem1, subitem1, 512, NULL);
::ReadProcessMemory(process, _subitem2, subitem2, 512, NULL);
::ReadProcessMemory(process, _subitem3, subitem3, 512, NULL);
::ReadProcessMemory(process, _subitem4, subitem4, 512, NULL);
::ReadProcessMemory(process, _subitem5, subitem5, 512, NULL);
::ReadProcessMemory(process, _subitem6, subitem6, 512, NULL);
::ReadProcessMemory(process, _subitem7, subitem7, 512, NULL);
//::ReadProcessMemory(process, _subitem8, subitem8, 512, NULL);
char output[2048];
sprintf(output, “\”%d\”,\”%s\”,\”%s\”,\”%s\”,\”%s\”,\”%s\”,\”%s\”,\”%s\”,\”%s\””,lineCount,item,subitem1,subitem2,subitem3,subitem4,subitem5,subitem6,subitem7);
fprintf(out,”%s\n”,output);
lineCount++;
}
fclose(out);
}
::VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);
::VirtualFreeEx(process, _item, 0, MEM_RELEASE);
::VirtualFreeEx(process, _subitem1, 0, MEM_RELEASE);
::VirtualFreeEx(process, _subitem2, 0, MEM_RELEASE);
::VirtualFreeEx(process, _subitem3, 0, MEM_RELEASE);
::VirtualFreeEx(process, _subitem4, 0, MEM_RELEASE);
::VirtualFreeEx(process, _subitem5, 0, MEM_RELEASE);
::VirtualFreeEx(process, _subitem6, 0, MEM_RELEASE);
::VirtualFreeEx(process, _subitem7, 0, MEM_RELEASE);
}
}