블로그 이미지
평강왕자

카테고리

분류 전체보기 (35)
Programming Lv1 (32)
MFC (16)
Java (1)
C# (6)
Web (0)
DataBase (0)
WPF + Blend (8)
Qt (0)
Programming LV2 (0)
취미 (3)
Total
Today
Yesterday

달력

« » 2025.1
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

공지사항

최근에 올라온 글

다른프로그램의 창을 활성화 시켜야 할 경우가 있어야 할지도 모른다.
중요한건 윈도우 핸들값을 찾아야 한다.

1) 윈도우 핸들 값을 찾는다.
    1-1.클래스명을 모를경우 NULL을 집어넣고 Title에 흔히 보이는 프로그램 명을 집어넣어주면 된다.
          HWND hwnd = FindWindow(클래스명, Title);

    1-2. CreateProcess로 자신이 실행한 경우 PROCESS_INFORMATION 으로 윈도우 핸들값을 찾아야 한다.
          인터넷으로 콜백함수를 사용하여 프로세스를 뒤진다음 가져오는 함수가 있었다.
HWND m_hwnd;

BOOL CALLBACK EnumChildProc(  HWND hwnd,  LPARAM lParam  )
{
 m_hwnd = NULL;
 TCHAR text[255];
 DWORD dwPID = 0;
 GetWindowText(hwnd,text,sizeof(text));
 GetWindowThreadProcessId(hwnd,&dwPID);
 if(dwPID == (DWORD)lParam)
 {
   m_hwnd = hwnd;
  return FALSE;
 }
 return TRUE;
}

    2-1. 핸들 값을 찾았으면 그핸들값으로 창을 활성화 시킨다.
::BringWindowToTop(hwnd);
 ::SetActiveWindow(hwnd);
 ::SetForegroundWindow(hwnd);
 ::ShowWindow(hwnd, SW_SHOWNORMAL);
 ::UpdateWindow(hwnd);

Posted by 평강왕자
, |

1) 쓰레드 함수를 생성한다.

unsigned int UIUpdate(LPVOID dParam)
{
 CDSPNodeManagerUIDlg* mainDlg = (CDSPNodeManagerUIDlg*) dParam;
 
 return 0;
}

2) 사용할 곳에서 호출해준다.

::AfxBeginThread(UIUpdate, (LPVOID)this);

Posted by 평강왕자
, |


윈도우에 보면 트리에 three status 트리가 있다. 완전체크, 반체크, 해제 MFC 트리컨트롤은 기본적으로 지원하지 않아서 찾아보았다.

1) CTreeCtrl 을 상속받은 클래스 CCustomTreeCtrl을 만든다.

2) 메시지의 CUSTOMDRAW를 오버라이드한다.

3) CustomTreeCtrl 클래스에 체크 여부를 검사하는 BOOL GetStatus(HTREEITEM hItem) 함수를 만들어준고 CustomDraw에서 호출하여 체크 여부를 판단한뒤 색에 변화를 준다.

BOOL CCustomTreeCtrl::GetStatus(HTREEITEM hItem)
{
 HTREEITEM childItem = GetChildItem(hItem);
 while(childItem != NULL)
 {
  if(GetCheck(childItem))
  {
   return TRUE;
  }
  BOOL result = GetStatus(childItem);
  if(result == TRUE)
   return TRUE;

  childItem = GetNextSiblingItem(childItem);
 }
 return FALSE;
}

void CCustomTreeCtrl::CustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
 NMTVCUSTOMDRAW* pcd = (NMTVCUSTOMDRAW*)pNMHDR;
 HTREEITEM hItem;

 switch(pcd->nmcd.dwDrawStage)
 {
 case CDDS_PREPAINT:
  *pResult = CDRF_NOTIFYITEMDRAW;
  break;
 case CDDS_ITEMPREPAINT:
  hItem = (HTREEITEM)pcd->nmcd.dwItemSpec;
  //함수 결과 값이 TRUE면 색변화  
  BOOL result = GetStatus(hItem);
  if(result == TRUE)
  {
   pcd->clrText = RGB(255,0,0);
   pcd->clrTextBk = RGB(255,255,255);
  }
  pResult = CDRF_DODEFAULT;
  break;
 }
}

4) 트리컨트롤을 사용하고자 하는곳에서 CCustomTreeCtrl m_treeCtrl; 선언하여 사용하면 된다.

Posted by 평강왕자
, |


버튼에 이미지를 씌워야 하는데 그림파일이 버튼 크기보다 크면 이미지의 일부만 보인다.
그경우 이미지를 버튼크기에 맞게 다시 재설정을 해줘야 한다.

CString imagePath = _T("..\\picture\\picture.bmp");

CImage img;

img.Load(imagePath);

//버튼 크기에 맞게 이미지 재설정
 CDC dc;
 CRect rect;
 dc.Attach(lpDrawItemStruct->hDC);

 rect = lpDrawItemStruct->rcItem;

 CDC* pMDC = new CDC;

 pMDC->CreateCompatibleDC(&dc);

 CBitmap* pb = new CBitmap;
 pb->CreateCompatibleBitmap(&dc, rect.Width(),rect.Height());

 CBitmap* pob = pMDC->SelectObject(pb);

 pMDC->SetStretchBltMode(HALFTONE);

 img.StretchBlt(pMDC->m_hDC,-1,-1,rect.Width()+2,rect.Height()+2,0,0,img1.GetWidth(),img1.GetHeight(),SRCCOPY);

 pMDC->SelectObject(pob);
 CImage new_image;
 new_image.Attach((HBITMAP)(*pb));

 new_image.BitBlt(dc,rect.left,rect.top,SRCCOPY);

리소스의 버튼 속성의 Bitmap을 TRUE로 해줘야 한다.

p.s 해당 소스는 OnDrawItem을 상속받아 작성한 샘플입니다.

Posted by 평강왕자
, |

CString을 char*로 바꿔야 하는데
그냥 캐스팅을 하면 잘 안된다.

그래서 wcstombs을 사용하여 변환해 주는 방법을 사용 할 수 있다.

CString strCString = _T("TEST 문자열");
int strLen = strCString.GetLength();

char* strChar = new char[2*strLen + 1];
wcstombs(strChar, (wchar_t*)strCString.GetBuffer(0), 2*len + 1);

사용하여 변경할수 있다.
Posted by 평강왕자
, |

1차원 배열 동적 할당과 배열 크기를 알아야 하는경우가 있다.

//할당 new
int* array;
int = arraySize = 10;
array = new int[arraySize];

//할당 malloc
int* arry;
arry = (int*)malloc(sizeof(int)*10);

//배열의 크기
int size =  sizeof(array) / sizeof(array[0]);
Posted by 평강왕자
, |


간혹가다 프로토콜형태로 Char배열에 Byte형태로 전송하고 받아야 하는경우
long short 같은경우 비트 연산이 가능하지만 float 같은경우 비트연산이 불가능하다.

//샘플로 char배열과 float값 설정
char _charArray[4];
 float _floatValue = 12345.6789F;
//변환 전 값 체크
printf( " \n %10.5f " , _floatValue ) ;

//float 값을 unsigned log 으로 변환하여 한바이트씩 비트연산으로 배열에 집어 넣는다.
 _charArray[0] = (char)(*((unsigned long*)&_floatValue ) >> 24);
 _charArray[1] = (char)(*((unsigned long*)&_floatValue ) >> 16);
 _charArray[2] = (char)(*((unsigned long*)&_floatValue ) >> 8);
 _charArray[3] = (char)(*((unsigned long*)&_floatValue ));

//char배열에 집어넣은 값을 unsigned long 에 집어넣는다.
//여기서 & 0xFF를 제거할경우 부호 확장이 발생하여 값이 제대로 출력되지 않는다.
 unsigned long _longValue = (((unsigned long)_charArray[0]&0xFF) << 24);
  _longValue+= (((unsigned long)_charArray[1]&0xFF) << 16) ;
  _longValue+= (((unsigned long)_charArray[2]&0xFF) << 8) ;
  _longValue+= (((unsigned long)_charArray[3]&0xFF));;

//가져온값을 float로 변환한다.
 float fData = *((float*)&_longValue);
//변환후 값 출력
 printf( " \n %10.5f " , fData ) ;

이방법 말고 union을 사용하는 방법도 있다.

//union으로 float와 unsigned log 을 선언한다.
union {
  unsigned long l;
  float f;
 }u1,u2;

//u1구조체의 float에 값 삽입 ( unsigned log 에도 자동으로 값 삽입) 
u1.f = 1234.56789F;

//삽입된 값 출력
 printf( " \n %10.5f " , u1.f ) ;

//위에 예제와 다르게 부호확장을 위해서 unsigned char로 선언했다
//unsigned char일경우 부호가 없기 때문에 부호확장시 전부 0을 채워넣는다. 그래서 &0xFF가 필요 없다.
 unsigned char c[4];
 c[0] = u1.l >> 24;
 c[1] = u1.l >> 16;
 c[2] = u1.l >> 8;
 c[3] = u1.l;

 u2.l = c[0]<< 24;
 u2.l |= c[1]<< 16;
 u2.l |= c[2]<< 8;
 u2.l |= c[3];

  //u2.l = (c[0] & 0xFF) << 24;
 //u2.l |= (c[1] & 0xFF) << 16;
 //u2.l |= (c[2] & 0xFF) << 8;
 //u2.l |= (c[3] & 0xFF);

 printf( " \n %10.5f " , u2.f ) ;

Posted by 평강왕자
, |
MDI를 사용하면 다른 창에서 다른창을 호출해야 하는경우가 생긴다.
그경우 창을 구분해야 하는데.. 활성창을 가져오는건 함수가 있어서 간단하다.
메인프레임에서 차일드 객체를 가져와서 활성화되어있는 창을 부르면 포인터를 넘겨준다.

//메인프레임
CMainFrame *pFrame = (CMainFrame*)AfxGetMainWnd();
//차일드 프레임
CChildFrame *pChild = (CChildFrame*)pFrame->GetActiveFrame();
//활설화 View
CPerformanceMonitoringOneViewView *pView = (CPerformanceMonitoringOneViewView*)pChild->GetActiveView();

창이 여러개일경우 활성창이 아닌 다른창을 가져오는경우는 조금 다르다.
App 에서 Doc를 호출하여 현재 View의 목록을 가져와서 호출한다.

CWinApp* pApp = AfxGetApp();
POSITION posTemplate;
posTemplate = pApp->GetFirstDocTemplatePosition();
while(posTemplate)
{
 CDocTemplate* pDocTemplate;
 pDocTemplate = pApp->GetNextDocTemplate(posTemplate);
 POSITION posDoc = pDocTemplate->GetFirstDocPosition();
 while(posDoc)
 {
  CTestDoc* pDoc2 = (CTestDoc*)pDocTemplate->GetNextDoc(posDoc);
  POSITION posView = pDoc2->GetFirstViewPosition();
  while(posView)
  {
   CTestView* pView = (CTestView*)pDoc2->GetNextView(posView);
   pView->m_graphDlg->Test();
  }
 }
}
Posted by 평강왕자
, |

MFC MDI에 새창열기를 하면 OnFileNew 함수를 호출하여 새창을 연다.

ON_COMMAND(ID_FILE_NEW, &CWinAppEx::OnFileNew)

이부분을 약간 수정하여 원하는 함수를 호출하여 원하는데로 변경이 가능하다.

ON_COMMAND(ID_FILE_NEW, &CTestApp::CreateWindowGraph)

이런식으로 App안에 CreateWindowGraph라는 함수를 생성후 호출하여 변경하면 된다.

Posted by 평강왕자
, |

Pane 이용시 닫기 버튼을 없애거나 스타일을 바꿔야 하는경우가 생긴다.
그런경우 실제로 스타일변경을 해봐도 잘 되지 않거나 처음에만 적용되고 다시 실행할경우 적용이 되지 않는 경우가 있는데..
레지스트리에 CDockingManager의 내용을 저장하기 때문인거 같다..

//탭패널 생성
CTabbedPane* pTabbedPane = new CTabbedPane(TRUE);

 if(!pTabbedPane->Create(_T(""),this,CRect(0,0,255,100),TRUE,(UINT)-1, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_TOP | CBRS_FLOAT_MULTI, AFX_CBRS_REGULAR_TABS, AFX_CBRS_FLOAT | AFX_CBRS_RESIZE | AFX_CBRS_AUTOHIDE))
 {
  return -1;
 }

//패널 생성
m_networkManagerPane.Create(_T("NetworkManagerBar"),this,CRect(0,0,100,50),TRUE,1235, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_TOP | CBRS_FLOAT_MULTI, AFX_CBRS_REGULAR_TABS, AFX_CBRS_FLOAT | AFX_CBRS_RESIZE | AFX_CBRS_AUTOHIDE);

위코드는 닫기버튼을 적용시키지 않은 경우이다.
AFX_CBRS_REGULAR_TABS, AFX_CBRS_FLOAT | AFX_CBRS_RESIZE | AFX_CBRS_AUTOHIDE 이부분에 AFX_CBRS_CLOSE 추가되면 닫기 버튼이 생성된다.

이렇게 한후 실행하면 한번만 적용되고 차후 실행하면 적용이 되지 않는다.

regedit에 HKEY_CURRENT_USER -> Software -> 로컬 응용 프로그램 마법사에서 생성된 응용프로그램 항목에 보면 해당 프로젝트의 프로그램명이 보이고 Workspace -> DockingManager-128 이라는 항목을 삭제하고 시작하면 한번은 다시 적용되지만 차후 실행하면 여전히 적용이 되지 않는다.

그래서 프로그램에서 레지스트리를 초기화 시켜줘야 한다.

App 부분에 InitInstance() 함수에 프레임창을 만들기전에 레지스트리를 초기화 시켜준다.

//레지스트리 초기화
 CleanState();
// 주 MDI 프레임 창을 만듭니다.
CMainFrame* pMainFrame = new CMainFrame;
 if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))
 {
  delete pMainFrame;
  return FALSE;
 }

이경우 스타일은 적용되지만 레지스트리를 초기화 했기때문에 상태바나 이런설정이 매번 다시 초기화 되니 주의해야 한다.

'Programming Lv1 > MFC' 카테고리의 다른 글

MFC MDI 창에 메세지 보내기  (0) 2011.08.16
MFC 새창열기 변경  (0) 2011.08.16
MFC 바탕화면 해상도 가져오기  (0) 2011.08.16
MFC Argument 가져오기  (0) 2011.08.16
MFC Title bar 제거  (0) 2011.08.16
Posted by 평강왕자
, |

최근에 달린 댓글

글 보관함