ToolBar 이어붙이기

ToolBar를 이어 붙이기

CMainFrame에 다음과 같은 함수를 추가한다.

void CMainFrame::DockControlBarLeftOf(CToolBar* Bar, CToolBar* LeftOf)
{
 CRect rect;
 DWORD dw;
 UINT n;

 // get MFC to adjust the dimensions of all docked ToolBars
 // so that GetWindowRect will be accurate
 RecalcLayout(TRUE);

 LeftOf->GetWindowRect(&rect);
 rect.OffsetRect(1,0);
 dw=LeftOf->GetBarStyle();
 n = 0;
 n = (dw&CBRS_ALIGN_TOP) ? AFX_IDW_DOCKBAR_TOP : n;
 n = (dw&CBRS_ALIGN_BOTTOM && n==0) ? AFX_IDW_DOCKBAR_BOTTOM : n;
 n = (dw&CBRS_ALIGN_LEFT && n==0) ? AFX_IDW_DOCKBAR_LEFT : n;
 n = (dw&CBRS_ALIGN_RIGHT && n==0) ? AFX_IDW_DOCKBAR_RIGHT : n;

 // When we take the default parameters on rect, DockControlBar will dock
 // each Toolbar on a seperate line. By calculating a rectangle, we
 // are simulating a Toolbar being dragged to that location and docked.
 DockControlBar(Bar,n,&rect);
}

사용예)

m_wndToolBar1.EnableDocking(CBRS_ALIGN_ANY);
 m_wndToolBar2.EnableDocking(CBRS_ALIGN_ANY);
 EnableDocking(CBRS_ALIGN_ANY);
 DockControlBar(&m_wndToolBar1);
 DockControlBarLeftOf(&m_wndToolBar2,&m_wndToolBar1);

출처 : CodeProject
http://www.codeproject.com/docking/toolbar_docking.asp?df=100&forumid=54&exp=0&select=1013370

Dialog EditBox에서 엔터키 처리

Dialog에서는 Edit에서 Enter키를 Want Return을 지정하더라도 Enter키 입력시 다이어로그가 종료된다.

1. PreTranslateMessage(MSG* pMsg)를 다음과 같이 오버라이드 한다.
2. 엔터키 입력시 원하는 처리를 각각 추가 한다.

BOOL CHMC_CleanerDlg::PreTranslateMessage(MSG* pMsg)
{
 if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)
 {      
  if (GetDlgItem(IDC_EDIT1) == GetFocus())
  {
   return TRUE;
  }
  if (GetDlgItem(IDC_EDIT2) == GetFocus())
  {
   // 여기에 추가
   return TRUE;
  }
  if (GetDlgItem(IDC_EDIT4) == GetFocus())
  {
   // 여기에 추가
   return TRUE;
  }
 }
 return CDialog::PreTranslateMessage(pMsg);
}

 

Listview컨트롤 Text가져오기


I was recently trying to steal strings from another program’s listview control. You need to pass a pointer so it knows where to put the string. Normally this wouldn’t be a problem, but because Windows uses virtual memory pointers are not valid across programs.


Virtual memory is how Windows deals out memory to all it’s programs. It makes programs think they have 2 Gb of memory to use. It also protects programs from using each other’s memory so if one program crashes it doesn’t take down the whole system with it.


So after coding a fair bit, I realized my pointers were all invalid and it wouldn’t work. A few hours of digging through MSDN brought me to the functions VirtualAllocEx(), VirtualFreeEx(), WriteProcessMemory() and ReadProcessMemory(). Armed with this new information, I set out to modify my code. Here is what I had so far:


Collapse
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <windows.h>
#include <commctrl.h>
int main(void) {
/* Run through the windows until we find our listview. */
HWND hwnd=FindWindow(NULL, “Stealing Program’s Memory: ListView”);
HWND listview=FindWindowEx(hwnd, NULL, “SysListView32”, NULL);
int count=(int)SendMessage(listview, LVM_GETITEMCOUNT, 0, 0);
int i; char item[512], subitem[512];
/* Shove all items of listview into item and subitem
and print out one by one. */
LVITEM lvi;
lvi.cchTextMax=512;
for(i=0; i<count; i++) {
lvi.iSubItem=0;
lvi.pszText=item;
SendMessage(listview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)&lvi);
lvi.iSubItem=1;
lvi.pszText=subitem;
SendMessage(listview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)&lvi);
printf(“%s – %s\n”, item, subitem);
}

return 0;
}


As I said before, this won’t work. The pointers to lvi, item, and subitem all get screwed when they go across process. The solution? Use WriteProcessMemory() and ReadProcessMemory() to use the other programs memory, perform LVM_GETITEMTEXT on it, and read it back. Hackish yes, but then again reading items from another program’s listview control is one giant hack.


First, we get the process of the listview like this:

 unsigned long pid;
HANDLE process;
GetWindowThreadProcessId(listview, &pid);
process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|
PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, pid);

Next We create three pointers, LVITEM *_lvi, char *_item, and char *_subitem and allocate them in the other program’s virtual memory space with VirtualAllocEx():

LVITEM *_lvi=(LVITEM*)VirtualAllocEx(process, NULL, sizeof(LVITEM),
MEM_COMMIT, PAGE_READWRITE);
char *_item=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
PAGE_READWRITE);
char *_subitem=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
PAGE_READWRITE);

Now we point lvi.pszText to _item, and copy it’s memory to _lvi using WriteMemoryProcess():

lvi.pszText=_item;
WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);

Now that we have an LVITEM pointer that is valid in the other programs virtual memory, we can shoot off LVM_GETITEMTEXT to listview and copy _item‘s text into item so we can read it in our program:

SendMessage(hwnd, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
ReadProcessMemory(process, _item, item, max, NULL);

Repeat that for subitem, then free the memory we used in the other program’s memory:

VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);
VirtualFreeEx(process, _item, 0, MEM_RELEASE);
VirtualFreeEx(process, _subitem, 0, MEM_RELEASE);

Yay, all done. In case that didn’t make too much sense to you, here is our new code, all fixed up:


Collapse
#define WIN32_LEAN_AND_MEAN #include <stdio.h> 
#include <windows.h>
#include <commctrl.h>
int main(void) {
HWND hwnd=FindWindow(NULL, “Stealing Program’s Memory: ListView”);
HWND listview=FindWindowEx(hwnd, NULL, “SysListView32”, NULL);
int count=(int)SendMessage(listview, LVM_GETITEMCOUNT, 0, 0);
int i;
LVITEM lvi, *_lvi;
char item[512], subitem[512];
char *_item, *_subitem;
unsigned long pid;
HANDLE process;
GetWindowThreadProcessId(listview, &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);
_subitem=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
PAGE_READWRITE);
lvi.cchTextMax=512;
for(i=0; i<count; i++) {
lvi.iSubItem=0;
lvi.pszText=_item;
WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
SendMessage(listview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
lvi.iSubItem=1;
lvi.pszText=_subitem;
WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
SendMessage(listview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
ReadProcessMemory(process, _item, item, 512, NULL);
ReadProcessMemory(process, _subitem, subitem, 512, NULL);
printf(“%s – %s\n”, item, subitem);
}
VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);
VirtualFreeEx(process, _item, 0, MEM_RELEASE);
VirtualFreeEx(process, _subitem, 0, MEM_RELEASE);
return 0;
}

If you’re looking to use a program’s memory for another reason, or have had a similar problem to mine, adapting this should be fairly easy.

출처- codeproject-