'API & MFC'에 해당되는 글 48건

  1. 2010.03.10 디버그모드 & 릴리즈모드
  2. 2010.03.10 사운드출력함수
  3. 2010.03.10 좌표가 영역안에 있는지 확인
  4. 2010.03.08 UpdateData함수
  5. 2010.03.04 각 클래스에서 객체 얻기
  6. 2010.02.13 메시지 기본원리
  7. 2010.02.10 프로세스
  8. 2010.02.09 우아한 종료
  9. 2010.02.09 ATOM
  10. 2010.02.05 EventSelect(클)
프로젝트를 컴파일하여 실행 파일을 만드는 방법에는 디버그/릴리즈 두 가지가 있다.

 디버그 빌드와 릴리즈 빌드에서 서로 실행 결과가 다른 경우, 특기 디버그 빌드에서는 괜찮은데 릴리즈 빌드에서만 오류가 발생하여 프로그램이 죽는 경우가 있는데 이런 경우는 대부분 메모리가 깨진 경우에 발생한다. 두 모드에서 동적으로 메모리를 할당하면 힙 영역에 요청한 크기만큼 메모리를 할당 받게 되는데 그 초기값이 다르다.

릴리즈 빌드의 경우 할당된 메모리 영역을 초기화하지 않는 경우 바로 할당되기 직전의 쓰레기 값이 그대로 사용되는 반면 디버그 빌드의 경우 디버거로 디버깅하는데 블록을 구분하기 위해 0xCC, 0xDD와 같은 값으로 초기화된다.

 

디버그 모드

 실행 파일에 디버깅 정보를 삽입하여 언제든지 디버깅을 할 수 있도록 하며 프로젝트 디렉토리 아래에 Debug 서브 디렉토리에 실행 파일을 만들어 준다. 디버깅 정보가 들어가 있기 때문에 실행 파일의 상태를 확인할 수 있다.

 

릴리즈 모드

 일체의 디버깅 정보를 삽입하지 않을 뿐만 아니라 코드를 최적화하여 실행 파일 크기를 최대한 줄여준다. 릴리즈 모드로 만든 실행 파일로는 디버깅을 할 수 없지만 속도나 크기면에서는 디버그 모드로 만든 실행 파일보다 월등히 유리하다. 모든 버그를 잡고 개발이 완료되었을 때는 릴리즈 모드로 컴파일해야 한다.

 

 

출처 www.winapi.co.kr

'API & MFC > MFC & COM' 카테고리의 다른 글

SDK와 MFC  (0) 2010.03.11
프로퍼티시트 적용&도움말 지우기  (0) 2010.03.11
사운드출력함수  (0) 2010.03.10
좌표가 영역안에 있는지 확인  (0) 2010.03.10
UpdateData함수  (0) 2010.03.08
Posted by 아몰라
BOOL PlaySound(
LPCSTR pszSound,
HMODULE hmod,
DWORD fdwSound );


#pragma comment(lib, "winmm")
#include <mmsystem.h>

/* 경로를 설정하여, wave 파일을 재생하고자 할때 */
PlaySound("c:\test.wav" , NULL, SND_ASYNC);
/* wave 파일을 리소스에 등록 후, 재생하고자 할 때  */
PlaySound((LPCSTR)MAKEINTRESOURCE(IDR_WAVE1), NULL, SND_ASYNC | SND_RESOURCE);


SND_NODEFAULT - 파일이 없을때 경고음 안울리게!!

정지
PlaySound(NULL, NULL, NULL);

첫번째 인자 : 연주할 파일 이름
두번째 인자: 연주할경우 리소스를 가진 실행파일의 핸들
세번째 인자: 기타 옵션을 지정
SND_ASYNC - 비동기화된연주를 하는겁니다,,예를 들어서 음악이 재생돼면서 다른작업을 동시에 할때이것을 쓴다. SND_SYNC -  동기화된연주 즉 이렇게설정을 하면 프로그램은 이곡이 끝나기전까지는 아무반응을 안한다.
SND_LOOP - 반복연주한다는 뜻
SND_RESOURCE - 리소를 사용할때 사용한다.

'API & MFC > MFC & COM' 카테고리의 다른 글

프로퍼티시트 적용&도움말 지우기  (0) 2010.03.11
디버그모드 & 릴리즈모드  (0) 2010.03.10
좌표가 영역안에 있는지 확인  (0) 2010.03.10
UpdateData함수  (0) 2010.03.08
각 클래스에서 객체 얻기  (0) 2010.03.04
Posted by 아몰라
rect에

CRect rect;
 GetDlgItem(IDB_BITMAP2)->GetWindowRect(&rect);
 ScreenToClient(&rect);

이런식으로 일정 영역을 구해놓고

확인해보고싶은 좌표를 인자로 넣어주면

rect.PtInRect(point);

영역안에 들어가는지 안들어가는지

bool로 반환해준다.

'API & MFC > MFC & COM' 카테고리의 다른 글

프로퍼티시트 적용&도움말 지우기  (0) 2010.03.11
디버그모드 & 릴리즈모드  (0) 2010.03.10
사운드출력함수  (0) 2010.03.10
UpdateData함수  (0) 2010.03.08
각 클래스에서 객체 얻기  (0) 2010.03.04
Posted by 아몰라



DDX로 에디트와 변수를 묶어주고 UpdateData로 True를 줬을때는 변수로 false일 때는 에디트로 업데이트를 해준다.

'API & MFC > MFC & COM' 카테고리의 다른 글

프로퍼티시트 적용&도움말 지우기  (0) 2010.03.11
디버그모드 & 릴리즈모드  (0) 2010.03.10
사운드출력함수  (0) 2010.03.10
좌표가 영역안에 있는지 확인  (0) 2010.03.10
각 클래스에서 객체 얻기  (0) 2010.03.04
Posted by 아몰라

 

 

 

각 클래스에서 객체 얻기

 

 

 

MainFrame 얻기

CMainFrame *pFrame = (CmainFrame *) AfxGetMainWnd();

 

App 포인터 얻기

CTestApp *pApp = (CtestApp *) AfxGetApp();

 

Document 포인터 얻기(새로 만든 클래스에서 얻어올때)

#include "TestDoc.h"

#include "MainFrm.h"

 

CTestDoc *pDoc = (CTestDoc*)((CMainFrame *)AfxGetMainWnd())->GetActiveDocument();

 

GetParentFrame에서 GetActiveDocument 찾기

CDrawDoc * pDoc = (CDrawDoc*)GetParentFrame()->GetActiveDocument();

 

View 포인터 얻기(새로 만든 클래스에서 얻어올때)

#include "TestView.h"

#include "MainFrm.h"

CTestView *pView = (CTestView*)((CMainFrame *)AfxGetMainWnd())->GetActiveView();

 

자식 Dialog에서 부모 Dialog 포인터 얻기

CParent* pDlg = (CParent*)GetParent();

 

부모 Dialog에서 자식 Dialog 포인터 얻기

CChild dlg.m_variant;

 

CView에서 CDocument 객체 얻어올때

GetDocument()

 

CView에서 CFrameWnd 객체 얻어올때

GetParentFrame()

 

CDocument에서 CView객체 얻어올때

GetFirstViewPosition(), GetNextView()

 

CFrameWnd에서 CView 객체 얻어올때

GetActiveView()

 

CFrameWnd에서 CDocument 객체 얻어올때

GetActiveDocument()

 

Afx로 시작하는 함수는 전역함수라 어디서든 사용가능

AfxAbort()

어플리케이션 무조건 종료

AfxMessageBox()

메시지 상자를 표시

AfxGetApp()

어플리케이션 객체의 포인터 리턴

AfxGetAppName()

어플리케이션 명을 리턴

AfxGetMainWnd()

메인 프레임 윈도우 포인터 리턴

AfxGetInstanceHandle()

현재 인스턴스 핸들 리턴



'API & MFC > MFC & COM' 카테고리의 다른 글

프로퍼티시트 적용&도움말 지우기  (0) 2010.03.11
디버그모드 & 릴리즈모드  (0) 2010.03.10
사운드출력함수  (0) 2010.03.10
좌표가 영역안에 있는지 확인  (0) 2010.03.10
UpdateData함수  (0) 2010.03.08
Posted by 아몰라

 

RESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);


첫번째 인수(HWND hWnd) : 메시지를 받을 윈도우 핸들. 클래스로부터 여러 개의 윈도우가 만들어

졌을 때 어떤 윈도우로 전달된 메시지 인지를 구분해야 하므로 이 인수가 필요함.

두번째 인수(UINT iMessage) : Message ID이며 0x00 ~ 0x3FF 사이의 값이다. “WM_”으로 시작하는 상수로 정의 되어 있다.(전달된 메시지의 값)

WPARAM wParam, LPARAM lParam : 32비트 정수값이며 메시지의 추가 정보를 가진다.


메시지 큐


 

 

메시지는 시스템이나 사용자에 의해 발생한다.

키보드나 마우스 등의 사용자 입력 시 시스템은 이 입력에 대해 메시지를 발생시키며 또한

시스템 상황 변화를 통지하기 위해서도 메시지를 발생시킨다. 응용 프로그램도 윈도우간의

통신을 위해 메시지를 발생하며 특정 함수 호출에 의해 간접적으로 메시지가 발생하기도 한다.

윈도우즈라는 운영체제는 끊임없는 메시지의 생성과 처리를 무수히 반복하면서 실행되는

것 이므로 메시지는 윈도우즈 운영체제에서 중요하다고 할 수 있다.

메시지는 크게 메시지큐로 들어가는 (Queued)메시지와 큐에 들어가지 않고 곧바로

윈도우 프로시저로 보내지는 비큐(Non Queued)메시지로 구분된다.



 

윈도우 프로시져(Window Procedure) : 메시지를 처리하는 함수

 

- 윈도우 클래스당 하나씩 배정되며 메시지에 대응하는 방식을 정의하여 윈도우의 행동 양식을

   결정한다.

- 윈도우 클래스로부터 생성된 모든 윈도우의 메시지는 이 함수가 처리한다.

- 이름은 사용자가 마음대로 바꿀 수 있으나 일반적으로 WndProc이라는 이름을 사용한다.

- 4개의 인수를 가지며 정수값 하나를 리턴한다. 대부분 잘 처리했으면 0을 리턴하지만 어떤

   메시지는 처리 결과를 운영체제로 리턴하여 보고하는 경우도 있다.

Ex) WM_CREATE 는 초기화 과정에서 에러가 없으면 0을 리턴 에러가 발생했으면 -1을 리턴한다.

      WM_NCHITTEST  는 마우스가 윈도우의 어떤 부분에 있는지를 리턴한다.

  *WM_NCHITTEST : 윈도우에게 커서가 움직이거나 마우스버튼이 눌리거나 띄어졌을 때 메시지를 보낸다.



 




v  Window Procedure

모든 윈도우는 메시지를 처리하기 위해 메시지 처리 함수가 있어야 한다. 메시지 처리 함수의 모양은 아래 같다.

LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

윈도우 클래스를 만들때 메시지 처리함수의 주소를 등록한다.

v   Non-Queued Message

사용자가 윈도우를 만들기 위해 CreateWindowEx()함수를 호출하면 윈도우가 만들어 지고 윈도우가 만들어 졌다는 사실을 사용자에게 알리기 위해 WM_CREATE라는 메시지가 메시지 처리함수에 전달된다.(메시지 처리 함수가 호출된다.)

이때 WM_CREATE 메시지는 Message Queue 놓이지 않고 직접 Window Procedure 전달 되는 이를 non-Queued Message라고 한다.

입력 메시지(마우스 메세지, 키보드 메시지) 제외한 대부분의 메시지가 non-Queued Message 이다.

 

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {

switch( msg )     {

case WM_CREATE:

                           MessageBox( 0, "WM_CREATE도착", "", MB_OK);

                           return 0;

  

}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE , LPSTR lpCmdLine, int nShowCmd)

{

HWND hwnd = CreateWindowEx(…);

ShowWindow(hwnd, nShowCmd);






v  Queue Message

마우스나 키보드 메세지들은 직접 Window Procedure 전달되지 않고 메시지 Queue 놓이게 되는데 이를 Queue Message라고 한다. Queue 놓인 메시지를 처리하려면 반드시 사용자가 Queue 놓여 있는 메시지를 가져오는 메시지 루프가 필요하다.

MSG msg;

while ( GetMessage( &msg, 0, 0, 0 ) )  {

       TranslateMessage(&msg);

       DispatchMessage(&msg);

}

GetMessage() 메시지 Q WM_QUIT 메시지가 있을 경우에만 FALSE 리턴한다. 그래서 코드는 WM_QUIT메세지가 Q 들어 올때 까지는 무한 루프가 된다.

v   프로그램의 종료

사용자가 만든 윈도우가 파괴될 나오는 메시지는 WM_DESTROY 이다. 그러므로 사용자가 윈도우를 파괴 해도 프로그램은 계속 메시지 루프를 돌게 된다.( 하지만 윈도우는 파괴 되었다.- 모니터 화면에는 이상 아무 것도 없다.)

윈도우를 1 만든 경우 프로그램의 main 윈도우가 파괴 프로그램을 같이 종료 되게 하려면 WM_DESTROY 메시지에서 WM_QUIT메세지를 메시지 Q 넣는 작업을 해야 한다.

case WM_DESTROY:

       PostQuitMessage( 0 );             return 0;

v   처리하지 않은 메시지

메시지 처리 함수에서 발생된 메시지를 처리하지 않은 경우 반드시 아래 함수로 보내서 default 처리가 되게 해야 한다.

LRESULT CALLBACK DefWindowProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);









메시지 루프

 

- 사용자에 의해 입력된 메시지는 시스템 메시지 큐에 일단 저장되고 스레드 메시지 큐로 이동했다가 메시지 루프에 의해 해당 윈도우의 윈도우 프로시저로 보내져 처리된다.

 - 메시지는 최종 처리되기 직전까지 계속 큐에 유지되는데 이때 메시지는 다음과 같이 정의된 구조체의 형태로 존재한다.


Typedef struct tagMSG{HWND hwnd; UINT message; PARAM wParam; LPARAM lParam; WORD time; POINT pt;}MSG;


HWND
hWnd : 메시지를 받을 윈도우 핸들.

UINT iMessage : 전달된 메시지의 값

WPARAM wParam, LPARAM lParam : 메시지의 추가 정보를 가진다.

 

DWORD time : 메시지가 발생한 시간(time)

POINT pt : 발생시의 마우스 좌표(pt)

시간과 마우스 좌표는 모든 메시지들이 필요로 하는 정보가 아니므로 WndProc까지 전달되지 않는다.
필요할 경우 다음 두 함수를 사용하여 직접 조사해야 한다.

      ※ DWORD GetMessagePos(VOID) : 하위워드(LOWORD)x좌표, 상위워드(HIWORD)y좌표를 리턴한다.

      ※ LONG GetMessageTime(VOID) : 메시지 발생 시간을 부팅된 후 경과된 1/1000 단위로 리턴한다.


 

 - 메시지 루프는 메시지 큐에서 메시지를 꺼내 메시지 처리 함수로 보내는 일을 한다.

 - 보통 WinMain의 제일 끝부분에 위치하며 다음과 같이 그 형태가 정형화 되어 있다.


while(GetMessage(&Message,NULL,0,0)

{

     TranslateMessage(&Message);

     DispatchMessage(&Message);

}


- while문에 싸여져 있는데 이 루프는 프로그램이 끝날 때까지 계속반복된다.

    (메시지큐에 WM_QUIT[kwɪt]이라는 윈도우 메시지가 도착해 있으면 위의 반복문 조건속에 있는

     GetMessage함수는 FALSE값을 리턴하고 종료한다.)

      * WM_QUIT : PostQuitMessage 함수가 실행되면 발생하는 메시지

 

BOOL GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);

 

 - 스레드 메시지 큐에 대기중인 메시지를 꺼내 첫 번째 인수로 전달된 MSG 구조체에 복사한다.

 - 복사한 메시지를 큐에서 제거하고 TRUE리턴하며, 만약 큐에서 가져온 메시지가 WM_QUIT이면

    FALSE 리턴하여 메시지 루프를 탈출할 수 있다.

 

LPMSG lpMsg : MSG 구조체의 번지를 지정한다.

HWND hWnd : 현재 메시지를 큐에 올린 윈도우의 핸들값. 메시지를 처리해서 되돌려 줄때 필요하다.

UINT wMsgFilterMin : 회수된 메시지의 범위 중 최소값을 정수형태로 지정

UINT wMsgFilterMax : 회수된 메시지의 범위 중 최대값을 정수형태로 지정

 

*wMsgFilterMin : 첫번째 키보드 메시지인 WM_KEYFIRST 메시지 혹은 첫번째 마우스 메시지를 저장하는 WM_MOUSEFIRST 메시지 정수값을 저장한다.

*wMsgFilterMax : 마지막 키보드 메시지인 WM_KEYLAST 메시지 혹은 마지막 마우스 메시지를 저장하는 WM_MOUSELAST 메시지 정수값을 저장한다.

*wMsgFilterMin, wMsgFilterMax에 메시지의 범위를 지정하면 이 범위 내의 메시지만 가져온다.

*wMsgFilterMinwMsgFilterMax 인자의 값이 둘 다 0이면  GetMessage함수는 메시지 사용범위의  지정없이  모든 메시지를 돌려준다.

 

TranslateMessage


 
GetMessage 함수에 의해 큐로부터 가져온 메시지는 WM_QUIT가 아닌 한은 TranslateMessage 함수로 전달된다. 이 함수는 가상키 입력을 문자 입력(WM_CHAR)으로 바꾸는 역할을 하며 가상키 입력이 아닌 경우는 아무 처리도 하지 않는다.

* 컴퓨터의 가장 기본적인 입출력 장치는 아직까지는 키보드이다. 입력이 발생했을 경우 윈도우즈는 포커스를 가진 프로그램에게 키보드 메시지(WM_CHAR)를 보내주며 프로그램은 이 메시지를 받아 키보드 입력을 처리한다.(포커스(FOCUS)를 가진 프로그램이란 활성화되어 있는 윈도우를 말하며 한번에 오직 하나의 프로그램만 활성화 된다.멀티 태스킹 환경이라도 활성화될 수 있는 프로그램은 오직 하나밖에 없으며 활성화된 프로그램만 포커스를 가지고 키보드 입력을 받아들일 수 있다.


 

 DispatchMessage


메시지를
윈도우 프로시저로 보내 처리하도록 하는데 MSG 구조체의 hwnd 멤버를 보고 정확하게 목적 윈도우의 메시지 처리 함수로 배달한다. 윈도우 핸들로 부터 어떤 윈도우 프로시저에게 메시지를 전달할 것인가를 결정하는 중요한 일을 이 함수가 담당한다.




출처 - 선문비트 최강사님 도큐먼트

'API & MFC > API & 시스템프로그래밍' 카테고리의 다른 글

프로세스  (0) 2010.02.10
ATOM  (0) 2010.02.09
간단한 DLL 예제  (1) 2010.02.03
리스트뷰  (0) 2010.02.03
WM_USER And WM_APP  (0) 2010.02.02
Posted by 아몰라
정의  - 실행중인 프로그램 (파일이 실행되어 메모리에 적재되면 프로세스가 된다.)

내용 -  프로세스는 실행중인 프로그램이지만 작업의 주체는 아니다. 작업은 프로세스 내의 쓰레드가 담당한다.

프로세스는 각각 4GB의 주소 공간과 파일, 메모리, 스레드 등의 객체들을 소유하며 프로세스가 종료될 때 프로세스가 소유한 모든 자원은 운영체제의 의해 파괴된다. 모든 것은 프로세스의 의해 소유되며 스레드는 윈도우와 메시지 큐, 스택만 소유한다. 객체간의 소유 관계는 프로세스 > 스레드 > 윈도우 로 정리할 수  있다.



<프로세스 생성 함수> - WinExec, CreateProcess.

 

UINT WinExec (LPCSTR lpCmdLine, UINT uCmdShow)

한 프로그램에서 다른 프로그램을 실행하고자 할 때는 Win32 AP가 제공하는 프로세스 생성 함수를 사용한다. 프로세스를 생성하는 가장 간단한 함수는 WinExec이다

lpCmdLine

실행 시키고자 하는 프로그램의 이름, (완전 경로를 줄 수 있다.)

uCmdShow

실행 직 후 프로그램이 어떻게 보일지 지정.(기본 SW_SHOWNORMAL)

Ex)

UINT WinExec(“Notepad.exe”,SW_SHOWNORAML);

 

BOOL CreateProcess (LPCTSTR lpApplicationName, LPTSTR lpCmdLine,

LPSECURITY_ATTRIBUTES lpProcessAttributes,

LPSECURITY_ATTRIBUTES lpThreadAttributes,

BOOL bInheritHandles,  DWROD dwCreationFlags,

LPVOID lpEnvironment,  LPCTSTR lpCurrentDirectory,

LPSTARTUPINFO lpStartupInfo,

LPPROCESS_INFORMATION lpProcessInformation  );

프로세스를 생성하는 함수. 새로 만든 프로세스의 메인 윈도우가 어떻게 초기화될지 정하는 구조체인STARTUPINFO 구조체와 생성된 프로세스의 정보를 대입 받기 위한 구조체인 PROCESS_INFORMATION 구조체가 꼭 필요하다.[출처] [API] 프로세스|작성자 흡연토끼

à10개의 인수를 가지고 있는데 이 중 반드시 필요한 인수는 4가지 뿐이며 나머지는 NULL

줄 수 있다.

 

lpApplicationName

실행하고자 하는 프로세스 이름

lpCmdLine

명령행 인수를 지정한다.

bInheritHandles

상속 가능한 핸들에 대해 자식 프로세스에게 상속할지를 결정.(null)

lpStartupInfo

메인 윈도우의 초기화를 정하는 구조체.

lpProcessInformation

생성된 프로세스의 정보를 받기위한 구조체.

EX)

CreateProcess(NULL,”NotePad.exe”,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);






프로세스가 자기 자신을 종료하는 가장 간단하고 일반 적인 방법은 WM_CLOSE메시지를 보내거나 DestoryWindow로 메인윈도우를 파괴하는것이다. 이때 WM_DESTORY에서 PostQuitMessage를 호출하여 메시지 루프를 종료한다.

 

 

<프로세스 종료 함수>

 

- void ExitProcess(UNIT uExitCode);

 함수가 호출되면 프로세스는 정리 작업이 들어가고 즉각 종료된다.

 

     프로세스와 연결된 모든 DLL을 종료시키기 위해 각 DLL DllMain함수가 호출되며

        dll들은 스스로 정리 작업을 한다.

     열려진 모든 핸들을 닫는다.

     실행중인 모든 스레드를 종료한다.

     프로세스 커널 객체와 스레드 객체는 신호상태가 되며 이 객체를 기다리는 다른 프로세스는 대기상태를 해제한다.

     프로세스의 종료코드는 STILL_ACTIVE에서 ExitProcess가 지정한 종료값이 된다.

 

-BOOL TerminateProcess(HANDLE hProcess,UINT uExitCode);

 프로세스 외부에서 다른 프로세스를 종료하는 메소드, ExitProcess에 비해 종료 대상이 되는 프로세스의 핸들을 가지므로 자기 자신이 아닌 다른 프로세스를 강제로 종료 시킬 수 있다.

 

à TerminateProcess ExitProcess함수보다 더 위험하다. 이는 함수가 호출될 때는 동일한 작업이 수행되나 TerminateProcess는 연결된 DLL에게 종료 사실을 통지하지 않는다. 때문에 TerminateProcess함수로 강제로 프로세스를 종료한다면 정보를 잃어버리게 될 수 있다.


<프로세스 핸들>

윈도우즈는 GDI, USER, KERNEL의 세 가지 주요 DLL로 구성되어 있다. 각 모듈은 여러 종류의 객체를 관리하며 관리의 편의를 위해 핸들을 사용한다. 객체는 시스템 리소스를 나타내는 일종의 데이터 구조체이며 이 구조체들은 보통 덩치가 크기 때문에 좀 더 간단한 32비트 정수값의 핸들로 관리된다. 각 모듈별 객체에는 어떤 것들이 있고 특징은 어떤지 정리해보자.

모듈

객체

특징

USER

윈도우, 커서, 캐럿, 아이콘

한 오브젝트에 하나의 핸들. 시스템 전역적

GDI

, 브러시, 비트맵, 팔레트

한 오브젝트에 하나의 핸들. 프로세스 지역적

KERNEL

파일, 프로세스, 스레드, 이벤트

보안 적용. 프로세스 한정적


USER 객체 - ProA에서 윈도우를 만들고 핸들을 받으면 그 핸들을 ProB에게 전달하면 ProB는 윈도우 핸들을 사용하여 ProA가 만든 윈도우를 마음대로 만질수 있다.

GDI객체 - ProA에서 펜을 만들고 hPen 핸들을 발급받아서 ProB로 보냈다고해서 ProB가 이 펜을 사용할 수 없다. GDI 객체는 언제든지 원하는대로 생성할 수 있는데다 공유할 필요가 없기 때문에 프로세스 지역적이다.

커널객체 - 윈도우즈는 멀티 유저를 지원하는데 파일이나 프로그램 모두 소유자를 지정할 수 있고 소유자만 액세스 하도록 권한을 설정할 수 있다. 그래서 커널 객체를 만드는 CreateProcess, CreateFile, CreateMutex 등의 함수들은 모두 보안 속성을 인수로 가진다.

이런 보안상의 이유로 커널 객체는 프로세스 한정적이다.
(프로세스 한정적 - 한 프로세스가 만든 핸들은 다른 프로세스에서 곧바로 사용할 수 없되 대신 다른 프로세스가 같은 객체를 다시 오픈 하여 또 다른 핸들을 사용할 수 있다는 뜻이다.)

ProA가 ProC를 생성해서 ProC의 핸들을 받는다. 그리고 ProB에게 ProC의 핸들을 보내준다. 하지만 ProB는 ProC를 열 수 있는 권한이 아직 있는지 없는지 확인이 안되었기 때문에 사용못한다. ProB가 ProC를 액세스하고 싶다면 다음 함수로 프로세스의 ID로부터 프로세스 핸들을 다시 열어야 한다. 

ID
- 프로세스간의 구분을 위한 중복되지 않는 식별값일 뿐이며 ID로부터 직접 프로세스를 제어할 수는 없다. ID로부터 핸들을 발급받아야만 비로소 이 객체를 제어할 수 있다.

<프로세스의 핸들 얻는 함수>

 

HANDLE OpenProcess(DWORD dwDesiredAccess, BOOL blnheritHandle, DWORD dwProcessld)

dwDesiredAccess

Flag 접근

blnheritHandle

Flag 상속

dwProcessld

프로세스 identifier

 

<자기자신의 프로세스 핸들 얻는 함수>

HANDLE GetCurrentProcess (VOID);  : 필요한 인자는 없으며 자기자신의 프로세스 핸들 값을 반환한다.




<
프로세스 종료 상태를 구하는 함수>
                  
BOOL GetExitCodeProcess (HANDLE hProcess, LPWORD lpExitCode);

프로세스의 종료 상태를 구하는 인수로 프로세스의 핸들을 주면 이 프로세스의 종료 상태를 lpExitCode에 리턴 해준다.

hProcess

프로세스의 핸들

lpExitCode

DWORD의 포인터형. 프로세스의 상태코드가 넘어온다.        성공 1, 실패 0반환.

 

<사용 예>

static DWORD ProcID = 0;

static HANDLE hProc = 0;

 

switch (iMessage) {

           case WM_USER:

                     ProcID = wParam;

                     hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcID);

                     return 0;

           case WM_LBUTTONDOWN:

                     GetExitCodeProcess(hProc, &ExitCode);

           }



.[출처] [API] 프로세스|작성자 흡연토끼

'API & MFC > API & 시스템프로그래밍' 카테고리의 다른 글

메시지 기본원리  (0) 2010.02.13
ATOM  (0) 2010.02.09
간단한 DLL 예제  (1) 2010.02.03
리스트뷰  (0) 2010.02.03
WM_USER And WM_APP  (0) 2010.02.02
Posted by 아몰라

1. 소켓 연결 종료의 문제점(이는 TCP기반을 말한다.)

TCP 기반에서 closesocket()함수를 호출하게 되면 연결을 완전 종료한다는 의미이다. 여기에 한 가지 문제점이 있다.

 

만약 Host A Host B에게 메시지를 보내고 Host A closesocket 함수를 호출해 연결을 종료 했다면, Host B에서 Host A로 전송되고 있는 메시지가 있을 때, 그 메시지는 전송을 완료하지 못하고 중간에 소멸되고 말것이다. (여기서 closesocket함수는 출력 스트림과 입력 스트림을 모두 종료하는 기능을 한다.)

이 문제를 해결하기 위해 소켓 스트림의 일부만 종료(half close)하는 방법에 대해 알아볼 것이다.

 

다음은 half close를 하는 함수이다.

 

int shutdown(SOCKET s, int how);

s : half-close를 할 소켓의 핸들이다.

How : 종료모드를 인자로 전달한다.

 

다음에 how에 들어갈 종료모드들이다.

상수 값

모드

정의

0

SD_RECEIVE

입력 스트림 종료

1

SD_SEND

출력 스트림 종료

2

SD_BOTH

/ 출력 스트림 종료

 

다음과 같이 만약 출력 스트림만 종료를 하게 된다면, Host B에서 Host A로 전송중인 메시지는 입력 스트림이 아직 열려 있기 때문에 무사지 전송이 가능하게된다.

 

 

 

 

 

 

2. 출력 스트림의 종료의 필요성

메시지가 모두 무사히 전송되고 나서 closesocket를 이용해 종료하면 되지 출력 스트림의 종료가 왜 필요한 것인가?에 대해 알아보자.

 

출력 스트림을 종료하게 되면, 데이터 전송의 끝을 알려주는 EOF 메시지를 연결 되어 있는 호스트로 보내게 된다. 그리고 EOF 전송 시 상대 호스트의 데이터 수신함수(read, recv) 0을 반환한다.

 

출력 스트림을 종료하는 방법에는 shutdown 함수를 이용하여 종료 할 수도 있고, closesocket를 이용해도 입력 스트림과 함께 출력 스트림 또한 종료 되므로 EOF메시지가 전송된다.

 

다음 그림을 보면, 파일을 모두 보내고 EOF 메시지를 전송하고 있다. Clinet에서는 EOF메시지를 받고 파일이 모두 전송되었다는 것을 알아차리고 Thank you메시지를 보내게 된다. 만약 입력 스트림과 출력 스트림 모두 종료하게 된다면 Thank you 메시지는 받지 못할 것이다. 또한 EOF메시지를 보내지 않는다고 한다면, Client는 파일 전송이 언제 끝나는지도 모르는 채 파일이 전송을 계속 기다리게 되고, 한편 Server측에서는 파일을 다 전송하고 확인 메시지를 계속 기다리게 되어 server / client 모두 무한 대기 상태에 빠지게 된다.
 

 

'API & MFC > 네트워크프로그래밍' 카테고리의 다른 글

EventSelect(클)  (0) 2010.02.05
EventSelect(서버)  (0) 2010.02.05
EventSelect란?  (0) 2010.02.05
ASyncSelect 예제  (1) 2010.02.04
소켓통신의 라이브러리 사용 선택 시 고려사항  (0) 2010.02.02
Posted by 아몰라
아톰에 대해서 알기전에 아톰테이블에 대해서 먼저 알아보자.

아톰 테이블이란?

- 시스템이 유지하는 문자열 테이블
- 아톰들을 저장하는 해쉬테이블

아톰테이블에 문자열을 보관하면 저장된 문자열을 대표하는 정수값을 돌려준다. 그 값이 아톰이다.


 아톰 테이블의 종류


로컬 아톰테이블

- 지역아톰테이블에 저장
- 테이블을 만든 응용 프로그램 내에세만 사용가능
- 함수명 AddAtom, GetAtomName 등등


글로벌 아톰테이블

- 전역아톰테이블에 저장
- 시스템의 모든 응용 프로그램이 같이 사용
- 함수명 GlobalAddAtom, GloabalGetAtomName 등등

아톰함수정리

ATOM GlobalAddAtom(LPCTSTR lpString)
 <문자열 추가>
첫 번째 인자: 추가 하고자 하는 문자열
반환 값 : 아톰테이블에 추가된 문자열의 아톰을 준다.


ATOM GlobalDeleteAtom(ATOM nAtom) <문자열삭제>
첫 번째 인자: 삭제 하고자 하는 아톰
반환 값:  성공시 0 , 실패시 nAtom



UINT GlobalGetAtomName(ATOM nAtom, LPTSTR lpBuffer, int nSize)
 <아톰값으로부터 문자열 추출>
첫번재 인자: 헤당 아톰
두번째 인자: 아톰에서 찾은 문자열을 담을 버퍼공간

세 번째 인자:
버퍼공간 사이즈
반환 값:  실패 시 0


ATOM GlobalFindAtom(LPCTSTR lpString)
<문자열로부터 아톰값을 구한다.>
 

첫 번째 인자: 해당 문자열
반환 값 : 실패 시 0



아톰의 사용용도

- 문자열을 '키'로 가지는 자료들을 관리 할 때
     중복문자열을 저장하지 않는다.(Add함수로 같은 문자열을 저장하면 참조카운트가 늘어난다 1,2,3....Delete 함수로 참조인수가 0이 될 때 시스템은 아톰테이블에서 문자열삭제한다.)


- 문자열을 통한 해쉬함수가 필요한 경우








'API & MFC > API & 시스템프로그래밍' 카테고리의 다른 글

메시지 기본원리  (0) 2010.02.13
프로세스  (0) 2010.02.10
간단한 DLL 예제  (1) 2010.02.03
리스트뷰  (0) 2010.02.03
WM_USER And WM_APP  (0) 2010.02.02
Posted by 아몰라

#pragma comment(lib,"ws2_32")
#include <winsock2.h>
#include <iostream>

#define YOURIP "192.168.34.103"
#define YOURPORT 1100


struct App
{
 SOCKET sarr[WSA_MAXIMUM_WAIT_EVENTS];
 HANDLE hEarr[WSA_MAXIMUM_WAIT_EVENTS];
 HANDLE hFileArr[WSA_MAXIMUM_WAIT_EVENTS];
 int now;
};

void connectProc(int index);
void writeProc(int index);
void CloseProc(int index);
void DeleteSocket(int index);
void InitEvent(SOCKET sock);
void SendData(int index);


extern App app;




#include "event.h"

using namespace std;

App app; 

 

void main()
{
 WSADATA wsadata;
 WSAStartup(MAKEWORD(2,2),&wsadata);
 
 SOCKET sock;
 sock = socket(AF_INET, SOCK_STREAM, 0);

 SOCKADDR_IN client = {0,};

 client.sin_addr.s_addr = inet_addr(YOURIP);
 client.sin_family = AF_INET;
 client.sin_port = htons(YOURPORT);
 
 
 InitEvent(sock);
 
 WSAEventSelect(app.sarr[app.now],app.hEarr[app.now],FD_CONNECT);
 connect(sock,(SOCKADDR *)&client,sizeof(client));

 app.now++;

 WSANETWORKEVENTS ev;
 int index;
  
  

 while(1)
 {
  index = WSAWaitForMultipleEvents(app.now,app.hEarr,FALSE,WSA_INFINITE,FALSE);
  index -=  WSA_WAIT_EVENT_0;
  WSAEnumNetworkEvents(app.sarr[index],app.hEarr[index],&ev);

  switch(ev.lNetworkEvents)
  {
  case FD_CONNECT:
   connectProc(index);
   break;
  case FD_WRITE:
   writeProc(index);
   break;
  case FD_CLOSE:
   CloseProc(index);
   break;
  } 
 }
 

 WSACleanup();
}


void connectProc(int index)
{
 SOCKET sock = app.sarr[index];
 DeleteSocket(index);
 
 InitEvent(sock);
  
 WSAEventSelect(app.sarr[app.now], app.hEarr[app.now],FD_WRITE);
 app.now++;
}


void writeProc(int index)
{
 if(app.sarr[index])
 {
  while(1)
  {
   SendData(index);
  }
 }

}


void CloseProc(int index)
{
 WSACloseEvent(app.hEarr[index]);
 closesocket(app.sarr[index]);


 DeleteSocket(index);
}

void DeleteSocket(int index)
{
 app.now--;
 app.hEarr[index] = app.hEarr[app.now];
 app.sarr[index] = app.sarr[app.now];
}


void InitEvent(SOCKET sock)
{
 app.sarr[app.now] = sock;
 app.hEarr[app.now] = WSACreateEvent();
}


void SendData(int index)
{
 char str[100];
 printf("아무거나 입력해봐:\n");
 scanf("%s",str);

 SOCKET sock = app.sarr[index];
 send(sock,str,100,0);
}

'API & MFC > 네트워크프로그래밍' 카테고리의 다른 글

우아한 종료  (0) 2010.02.09
EventSelect(서버)  (0) 2010.02.05
EventSelect란?  (0) 2010.02.05
ASyncSelect 예제  (1) 2010.02.04
소켓통신의 라이브러리 사용 선택 시 고려사항  (0) 2010.02.02
Posted by 아몰라
이전버튼 1 2 3 4 5 이전버튼