출처 Dontcryme | dontcryme
원문 http://dontcryme.blog.me/30050646054

 

안녕하세요.

 

본 글은 다름아닌

MFC 기반에서 C#에서 만든 UserControl을 사용하는 방법에 대해서

설명드릴까 합니다.

 

먼저 아래와 같이 간단한 C# UserControl 을 하나 만듭니다.

(필요에 따라 '코프'에서 하날 받으셔도 됩니다.)

 

* UserControl을 만드는 과정을 설명하는 부분이 아니기 때문에 그림으로 과정설명은 대신합니다.

(1) Windows Forms 컨트롤 라이브러리를 선택 후 적당한 이름을 입력합니다.

 

 

(2) 간단하게 버튼하나가 들어간 UserControl을 생성합니다.

 

 

 

말 그대로 간단하게 하는 작업은 없고

 

10 namespace TestCSharpControlLibrary

11 {

12 public partial class UserControl1 : UserControl

13 {

14 public UserControl1()

15 {

16 InitializeComponent();

17 }

18

19 private void button1_Click(object sender, EventArgs e)

20 {

21 MessageBox.Show("Test 입니다.");

22 }

23 }

24 }

위 처럼 메세지 박스 하나 띄우는게 고작입니다.

자 그럼 빌드후에 생긴 Dll을 이용해 Test를 위해

MFC Dialog Based 프로젝트를 하나 생성합니다.

(생성과정은 생략)

(1) 아래와 같이 우선 "Static Text" 컨트롤을 하나 올려 놉니다.

후에 C# UserControl과 연결시키기 위해서...

(2) 다음은 기본 MFC 속성에서 공용언어 런타임 세팅을 "../clr" 이하로 바꿔 줍니다.

(3) 이제 남은 작업은 전에 만든 C# UserControl Dll을 참조해 주는 것과 사용하기 위해 컨트롤을 DDX 연결 시켜 주는 작업 등입니다.

- 먼저 아래와 같이 참조로 좀전에 생성된 dll을 걸어 줍니다.

[참조에 등록]

- 해당 MFC stdafx.h 내부의 아래에 Winform 형태의 사용을 위해 다음의 라인을 추가 합니다.

34 #include <afxcmn.h> // Windows 공용 컨트롤에 대한 MFC 지원입니다.

35 //헤더 추가

36 #include <afxwinforms.h> ->이녀석

37 //

38 #endif // _AFX_NO_AFXCMN_SUPPORT

- 컨트롤 사용을 위한 두 가지의 작업이 남았습니다. 먼저 생성한 Static Control연결을 위한 DDX를 위해

34 CWinFormsControl<TestCSharpControlLibrary::UserControl1> m_Ctrl;

형식 - [NamespaceName::ClassName]

위와 같이 해당 UserControl 객체를 선언한 뒤

59 DDX_ManagedControl(pDX, IDC_STATIC1, m_Ctrl);

위와 같이 DDX를 작성 후 빌드하면

위와 같습니다.^^

좋은 하루 되세요~~

 

'프로그래밍 > VC++ 개발 코딩' 카테고리의 다른 글

[본문스크랩] 쓰레드의 동기화  (0) 2014.01.17
GetMessage / PeekMessage 차이 설명  (0) 2014.01.17
마우스 라인 그리기  (0) 2014.01.17
WaitForMultipleObjects 사용  (0) 2014.01.17
출력 디렉토리  (0) 2014.01.17

마우스 왼쪽 버튼 클릭 후 드레그 하여 마우스이동중에 Line 그리고

 

* key point :

 

pDC->SetROP2(R2_NOTXORPEN);

// 기존의 선 지정하여, 기존 지울선을 그린다...

 

// 새로운 좌표로 그린다...

발췌..

 

http://msdn.microsoft.com/en-us/library/windows/desktop/ms687025%28v=vs.85%29.aspx

Waits until one or all of the specified objects are in the signaled state or the time-out interval elapses.

To enter an alertable wait state, use the WaitForMultipleObjectsEx function.

Syntax

DWORD WINAPI WaitForMultipleObjects(
  __in  DWORD nCount,
  __in  const HANDLE *lpHandles,
  __in  BOOL bWaitAll,
  __in  DWORD dwMilliseconds
);

Parameters

nCount [in]

The number of object handles in the array pointed to by lpHandles. The maximum number of object handles is MAXIMUM_WAIT_OBJECTS. This parameter cannot be zero.

lpHandles [in]

An array of object handles. For a list of the object types whose handles can be specified, see the following Remarks section. The array can contain handles to objects of different types. It may not contain multiple copies of the same handle.

If one of these handles is closed while the wait is still pending, the function's behavior is undefined.

The handles must have the SYNCHRONIZE access right. For more information, see Standard Access Rights.

bWaitAll [in]

If this parameter is TRUE, the function returns when the state of all objects in the lpHandles array is signaled. If FALSE, the function returns when the state of any one of the objects is set to signaled. In the latter case, the return value indicates the object whose state caused the function to return.

dwMilliseconds [in]

The time-out interval, in milliseconds. If a nonzero value is specified, the function waits until the specified objects are signaled or the interval elapses. If dwMilliseconds is zero, the function does not enter a wait state if the specified objects are not signaled; it always returns immediately. If dwMilliseconds is INFINITE, the function will return only when the specified objects are signaled.

Return value

If the function succeeds, the return value indicates the event that caused the function to return. It can be one of the following values. (Note that WAIT_OBJECT_0 is defined as 0 and WAIT_ABANDONED_0 is defined as 0x00000080L.)

Return code/value Description
WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount– 1)

If bWaitAll is TRUE, the return value indicates that the state of all specified objects is signaled.

If bWaitAll is FALSE, the return value minus WAIT_OBJECT_0 indicates the lpHandles array index of the object that satisfied the wait. If more than one object became signaled during the call, this is the array index of the signaled object with the smallest index value of all the signaled objects.

WAIT_ABANDONED_0 to (WAIT_ABANDONED_0 + nCount– 1)

If bWaitAll is TRUE, the return value indicates that the state of all specified objects is signaled and at least one of the objects is an abandoned mutex object.

If bWaitAll is FALSE, the return value minus WAIT_ABANDONED_0 indicates the lpHandles array index of an abandoned mutex object that satisfied the wait. Ownership of the mutex object is granted to the calling thread, and the mutex is set to nonsignaled.

If a mutex was protecting persistent state information, you should check it for consistency.

WAIT_TIMEOUT
0x00000102L

The time-out interval elapsed and the conditions specified by the bWaitAll parameter are not satisfied.

WAIT_FAILED
(DWORD)0xFFFFFFFF

The function has failed. To get extended error information, call GetLastError.

 

Remarks

The WaitForMultipleObjects function determines whether the wait criteria have been met. If the criteria have not been met, the calling thread enters the wait state until the conditions of the wait criteria have been met or the time-out interval elapses.

When bWaitAll is TRUE, the function's wait operation is completed only when the states of all objects have been set to signaled. The function does not modify the states of the specified objects until the states of all objects have been set to signaled. For example, a mutex can be signaled, but the thread does not get ownership until the states of the other objects are also set to signaled. In the meantime, some other thread may get ownership of the mutex, thereby setting its state to nonsignaled.

When bWaitAll is FALSE, this function checks the handles in the array in order starting with index 0, until one of the objects is signaled. If multiple objects become signaled, the function returns the index of the first handle in the array whose object was signaled.

The function modifies the state of some types of synchronization objects. Modification occurs only for the object or objects whose signaled state caused the function to return. For example, the count of a semaphore object is decreased by one. For more information, see the documentation for the individual synchronization objects.

To wait on more than MAXIMUM_WAIT_OBJECTS handles, use one of the following methods:

  • Create a thread to wait on MAXIMUM_WAIT_OBJECTS handles, then wait on that thread plus the other handles. Use this technique to break the handles into groups of MAXIMUM_WAIT_OBJECTS.
  • Call RegisterWaitForSingleObject to wait on each handle. A wait thread from the thread pool waits on MAXIMUM_WAIT_OBJECTS registered objects and assigns a worker thread after the object is signaled or the time-out interval expires.

The WaitForMultipleObjects function can specify handles of any of the following object types in the lpHandles array:

  • Change notification
  • Console input
  • Event
  • Memory resource notification
  • Mutex
  • Process
  • Semaphore
  • Thread
  • Waitable timer

Use caution when calling the wait functions and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. A thread that uses a wait function with no time-out interval may cause the system to become deadlocked. Two examples of code that indirectly creates windows are DDE and the CoInitialize function. Therefore, if you have a thread that creates windows, use MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx, rather than WaitForMultipleObjects.

Examples

For an example, see Waiting for Multiple Objects.

Requirements

Minimum supported client

Windows XP

Minimum supported server

Windows Server 2003

Header

WinBase.h (include Windows.h)

Library

Kernel32.lib

DLL

Kernel32.dll

See also

Synchronization Functions
Wait Functions

C# 및 C/C++ 출력 디렉토리 관리.

Bin : 실행파일 및 Dll

Config: 환경파일 XML

Source: 메일 소스.

Temp: 각종 Debug 파일.

1. 실행파일 및 Dll 생성 경로는 프로젝트 속성 창에서 지정 (첨부소스내 속성 참조)

2. sdf 파일 및 ipch 파일 경로 변경. 경로를 변경하면 소스내에 있었던 큰 파일들이 옮겨집니다.


3. C# Obj\Debug 폴더 파일 생성위치 변경. Tool 내부에서 제공하지는 않으며 각 프로젝트 마다 있는 *.csproj 파일에

하기의 내용 추가하면 됩니다.

) Warehouse.csproj Edit 창으로 열고 다음과 같이 추가한후 솔루션을 다시 빌드하면 추가한 경로에 Debug 폴더가 생깁니다.

<IntermediateOutputPath>..\..\Temp\obj\$(Configuration)\</IntermediateOutputPath>

이 작업을 한 이후에도 obj 폴더는 빈 상태로 계속 생성이 되는데 이 부분은 각 프로젝트 속성창에 있는 빌드 후 이벤트에 다음을 넣어주시면 됩니다.

이상입니다.

 

VS2010에서 sdf 파일 (SQL Server Compact Edition Database File(.sdf))이 생성되는데,

소스 압축을 하고자 할때 많은 용량이 차지하게된다.

 

이 파일은 디폴트로 생성되는것으로, 생성되지 않도록 VS2010 옵션을 변경하였다.

하기 그림을 참고 바람

(옵션 -> 텍스트 편집기 -> C/C++ -> 고급탭

대체(fallback) 위치 기본은 false로 되어있음 -> true로 변경하면됨)

 

 

XP에서 Aero 투명창 기능 사용방법이 마소에 기재되어있어 발췌함.

 

================================================================================================

권용 rodream@gmail.com|rodream.net에서 악성코드 제거기 <울타리>와 컴퓨터 최적화 프로그램인 <클릭 투 트윅>을 배포하고 있다. 2008년부터 비주얼 C++ 분야에서 마이크로소프트 MVP로 활용하고 있으며 데브피아 비주얼 C++ 분야의 시삽도 맡고 있다.

================================================================================================

 

마소 관련글

http://www.imaso.co.kr/?doc=bbs/gnuboard.php&bo_table=article&wr_id=37878

MSDN dwmapi 관련글

http://msdn.microsoft.com/ko-kr/library/aa969540.aspx

CreateThread 함수 static으로 사용하지 않고 작성하기

CreateThread 함수를 사용하다 보면 하기와 같이 구성해야 한다.

1. 클래스내에서 사용시 Static 멤버함수로 작성

2. 클래스 멤버가 아닌 함수로 작성 해야만 한다.

 

그러나 클래스내 멤버 함수로 정의하여 사용하는 경우,

멤버 변수에 접근이 불가능 하지 않은가..?!!

 

그렇다고 static으로 선언하게 되면 그안에서 사용되는 함수는

모두 static으로 선언해야만 한다.. 헉~!!

 

해서, 구글해보니..

 

요렇게 하면 된다..

 

static으로 ThreadProc를 선언하고, 이 함수의 인수를 this로 넘겨준다음

ThreadProc에서 인수를 클래스로 캐스팅해서 원하는 함수(static아님)를 호출하면 된다.

 

//--------------------------------------------------------

1. Thread 생성한 후

Sample::Init() {
HANDLE hThreadID = ::CreateThread(NULL, 0, WrapThreadProc, (void*)this,

0, &m_dwLAF_Thread);
CloseHandle(hThreadID);

}

 

//---------------------------------------------------------------------
2. Thread processing for wrap
DWORD WINAPI Sample::WrapThreadProc(LPVOID lParam)
{
Sample *test = (Sample *)lParam;
return test ->ThreadProc();
}

 

//---------------------------------------------------------------------
3. Thread processing body.
bool Sample::ThreadProc()
{

실제 제어되는 부분 ^^

}

 

앗싸`~!!

 

출처 원쉥이 | 원쉥이
원문 http://blog.naver.com/dnjstnpddl1/120122234879

C++ 소스 에러 목록

1. 'strcpy': 식별자를 찾을 수 없습니다.

- strcpy 함수를 포함한 헤더 string.h를 추가해준다.

2. estrcpy' : 매개 변수 2을(를) 'char'에서 'const char *'(으)로 변환할 수 없습니다.

- strcpy 함수에 들어가는 문자를 문자열로 선언해준다.

3. 'init' :참조되지 않은 지역 변수입니다.

- 사용되지 않는 변수이므로, 삭제해준다.

4. 구문 오류 : ')'이(가) '문자열' 앞에 없습니다.

- ')' 가 빠졌으므로, 빠진 위치에 적절히 추가해준다.

5. 'fopen' : 함수는 1개의 매개 변수를 사용하지 않습니다.

- fopen 에는 2가지 파라메터가 필요하다. 반드시 2가지를 추가해주도록 한다.

6. 'p_' : 선언되지 않은 식별자입니다.

- p_를 사용하기전에 이것이 무엇인지 반드시 선언해주어야한다.

7. 구문 오류 : ';'이(가) ')' 앞에 없습니다.

- ';' 가 빠졌으므로, 빠진 위치에 적절히 추가해준다.

8. '=' : 'char'에서 'char [100]'(으)로 변환할 수 없습니다.

- 등호 표시 '=' 는 양쪽이 같은 형일때만 사용할 수 있다. 양쪽을 같게 바꿔준다.

9. 'delete' : 포인터가 아닌 개체를 삭제할 수 없습니다.

- delete를 사용하는 개체가 포인터인지 확인하고 포인터가 아닐 시 해당 라인을 제거한다.

10. 'fprintf' : 매개 변수 1을(를) 'const char [9]'에서 'FILE *'(으)로 변환할 수 없습니다.

- fprintf 맨 앞에 파일 포인터 값을 넣어준다.

11. 구문 오류 : ')'이(가) 'return' 앞에 없습니다.

- return 구문 앞에 )를 삽입하여 블록을 닫아준다.

12. 오버로드된 'operator ->'의 'StudentInfo **' 반환 형식이 잘못되었습니다.

- -> 연산자를 사용하기 위해 사용된 변수를 포인터로 사용했는지 확인한다.

13.'student_number' : 'std::list<_Ty>::_Iterator<_Secure_validation>'의 멤버가 아닙니다.

- student_number 가 포인터의 멤버가 맞는지 확인한다.

14. '초기화 중' : 'std::list<_Ty>::_Iterator<_Secure_validation>'(으)로 변환할 수 없습니다.

- iterator을 호출한 개체에 '*' 가 붙어있는지 확인한다.

15. 이항 '!=' : 오른쪽 피연산자로 연산자가 없거나 허용되는 변환이 없습니다.

- iterator을 호출한 개체에 '*' 가 붙어있는지 확인한다.

16. 'StudentInfo' 형식에 오버로드된 멤버 'operator ->'가 없습니다.

- iterator을 호출한 개체에 '*' 가 붙어있는지 확인한다.

17. '->StudentInfo::student_number' : 왼쪽 피연산자에 'struct' 형식이 있습니다. '.'를 사용하십시오.

- '->' 포인터 호출 기호 대신 '.' 스트럭트 호출 기호로 바꿔서 사용한다.

18. 첨자는 배열 또는 포인터 형식을 사용해야 합니다.

- 첨자에 []를 붙이거나 *를 붙여준다.

19. 구문 오류 : ';'이(가) ')' 앞에 없습니다.

- ';' 가 빠졌으므로, 빠진 위치에 적절히 추가해준다.

20. 구문 오류 : ')'이(가) 'return' 앞에 없습니다.

- return 구문 앞에 )를 삽입하여 블록을 닫아준다.

21. 'jeongsu' : 선언되지 않은 식별자입니다.

- jeongsu를 사용하기전에 이것이 무엇인지 반드시 선언해주어야한다.

22. 'int'에서 'bool'(으)로 잘립니다.

- bool 로 선언된 것을 int 형으로 바꿔준다.

23. 왼쪽 피연산자는 l-value이어야 합니다.

- 왼쪽에 있는 피연사자를 상수가 아닌 변수로 바꿔준다.

24. '->student_number' 왼쪽은 클래스/구조체/공용 구조체/제네릭 형식을 가리켜야 합니다.

- student_number를 호출한 것이 무엇인지 확인하고 클래스/구조체/공용 구조체로 바꿔준다.

25. '->height' 왼쪽은 클래스/구조체/공용 구조체/제네릭 형식을 가리켜야 합니다.

- height를 호출한 것이 무엇인지 확인하고 클래스/구조체/공용 구조체로 바꿔준다.

26. 구문 오류 : '>'

- <> 안에 들어간 것이 무엇인지 확인하고 매개 변수로 올바르게 바꿔준다.

27. 'std' : 클래스 또는 네임스페이스 이름이 아닙니다.

- "stdlib.h" 헤더를 include 시켜준다.

28. 'iterator' : '`global namespace''의 멤버가 아닙니다.

- iterator을 호출한 매개 변수가 올바르게 사용되었는지 확인한다.

29. 'Compare2' : 값을 반환해야 합니다.

- return 구문을 붙여 함수에 맞는 값을 반환해준다.

30. 'fopen' : 함수는 1개의 매개 변수를 사용하지 않습니다.

- fopen 에 2개의 파라메터 값을 삽입해준다. 파일포인터, 파일모드의 2개.

31. '->std::list<_Ty>::push_back' : 왼쪽 피연산자에 'class' 형식이 있습니다. '.'를 사용하십시오.

- push_back 왼쪽에는 클래스 형식에 알맞는 '.' 기호를 사용한다.

32. 'std::list<_Ty>' 형식에 오버로드된 멤버 'operator ->'가 없습니다.

- 특정 함수를 호출할 때 사용되는 연산자가 '->' 로 잘못 사용되었으므로 '.' 로 바꿔준다.

33. 'getch': 식별자를 찾을 수 없습니다.

- conio.h 헤더를 include 해준다.

34. 이전 오류를 복구할 수 없습니다. 컴파일이 중지됩니다.

- 상위에 생긴 C++ 소스 에러를 모두 올바르게 수정하고 컴파일을 다시 시도한다.

35. 구문 오류 : ']'

- [] 표시가 제대로 열리고 닫혔는지 확인해준다.

36. 'fopen': This function or variable may be unsafe. Consider using fopen_s instead.

- 새로운 C++ 에서는 각 상황에 알맞는 형식의 내장함수가 새로 추가되었다. 상황에 맞게 바꿔주도록한다.

37. 'fscanf': This function or variable may be unsafe. Consider using fscanf_s instead.

- 새로운 C++ 에서는 각 상황에 알맞는 형식의 내장함수가 새로 추가되었다. 상황에 맞게 바꿔주도록한다.

38. 'printf': This function or variable may be unsafe. Consider using printf_s instead.

- 새로운 C++ 에서는 각 상황에 알맞는 형식의 내장함수가 새로 추가되었다. 상황에 맞게 바꿔주도록한다.

39. 'scanf': This function or variable may be unsafe. Consider using scanf_s instead.

- 새로운 C++ 에서는 각 상황에 알맞는 형식의 내장함수가 새로 추가되었다. 상황에 맞게 바꿔주도록한다.

40. 'StudentInfo' 다음에 'bool'이(가) 올 수 없습니다. ';'이 있어야 합니다.

- StudentInfo 뒤에 ; 종결문이 제대로 적혀있는지 확인하고 추가해준다.

41. 'return' : 'bool'에서 'StudentInfo'(으)로 변환할 수 없습니다.

- return 반환하는 부분에 bool 로 선언된 것이 올바른 것이 확인해준다.

42. 구문 오류 : ';'이(가) '}' 앞에 없습니다.

- ';' 기호가 제대로 적혀있는지, 위치를 확인한다.

43. 구문 오류 : '>'

- > 연산자가 올바르게 사용되었는지 확인한다. 대소 비교에 사용된다.

44. 'sqrt' : 오버로드된 함수에 대한 호출이 모호합니다.

- 제곱근을 구하는 함수에 인수를 double 형으로 임시 선언해준다.

45. 이항 '!=' : 오른쪽 피연산자로 연산자가 없거나 허용되는 변환이 없습니다.

- 오류가 난 줄의 != 연산자 좌우의 형을 비교하고 같은것인지 확인한다.

46. '<' : 의미 없는 연산자입니다. 파생 작업이 있는 연산자여야 합니다.

- < 연산자를 사용하기 이전에 그 바로 전의 연산이 제대로 되어있는지 확인한다.

47. 초기화되지 않은 'dummyDay' 지역 변수를 사용했습니다.

- dummyDay의 초기값을 설정해준다.

48. 'Sort': 식별자를 찾을 수 없습니다.

- Sort 함수를 메인함수 위에 적어, preprocessing 해준다.

49. 'gets': This function or variable may be unsafe. Consider using gets_s instead.

- 새로운 C++ 에서는 각 상황에 알맞는 형식의 내장함수가 새로 추가되었다. 상황에 맞게 바꿔주도록한다.

50. 'strcmp' : 매개 변수 1을(를) 'char [1][1]'에서 'const char *'(으)로 변환할 수 없습니다.

- 매개 변수를 임시로 (const char*) 로 선언해준다.

51. 'double'에서 'float'(으)로 잘립니다.

- float 으로 사용되는 것을 double 로 확장해준다.

52. 'temp' :참조되지 않은 지역 변수입니다.

- temp 는 사용되지 않는 변수이므로 삭제해주도록 한다.

53. 상수에 줄 바꿈 문자가 있습니다.

- 상수가 올바르게 상수만 적혀있는지 확인한다.

54. 'y' : 선언되지 않은 식별자입니다.

- y 로 선언된 변수가 있는지, 오타인지 확인한다.

55. ';' : 제어된 빈 문이 있습니다. 이 문이 필요합니까?

- 아무 명령이 없는 문장이므로 삭제해준다.

56. 'menu' 레이블이 정의되지 않았습니다.

- goto 문에 사용될 레이블의 위치를 지정해준다.

57. 'Sort' : 함수는 3개의 매개 변수를 사용하지 않습니다.

- Sort 라고 정의된 함수가 사용하는 매개 변수의 갯수에 따라 소스를 수정해준다.

58. 구문 오류 : int'은(는) ';' 다음에 와야 합니다.

- int 앞에 ';' 기호가 제대로 적혀있는지 확인하고 추가해준다.

59. 함수 호출에 인수 목록이 없습니다. '&std::list<_Ty>::size'을(를) 사용하여 멤버에 대한 포인터를 만드십시오.

- size 라는 함수가 ()를 붙여 포인터로 만들어서 사용되었는지 확인한다.

60. '<=' : 'int'에서 'unsigned int (__thiscall std::list<_Ty>::* )(void) const'(으)로 변환되지 않았습니다.

- '<=' 연산자 양쪽의 변수 형이 'int' 로 같게 맞춰준다.

 

source error tip

 

하기 사이트에서 발췌한 글입니다.
콜백함수란 어떠한 정보(또는 이벤트)를 관리하는 대상이 자신의 정보가 변경되거나 또는 이벤트가 발생할때
자신의 변경된 정보나 이벤트에 따른 어떠한 처리를 할 수 있도록 제공하는 함수라고 할 수 있습니다.

일단 우리 생활에서 예를 들자면

첫번째 상황.
철수와 영희가 놀이터에서 놀고있습니다. 철수는 엄마가 오후1시까지 집에 들어오라는 말을 듣고
시계에게 몇시인지 수시로 물어보다가 1시가되자 집으로 돌아갔습니다.

두번째 상황.
철수와 영희가 놀이터에서 놀고있습니다. 철수는 엄마가 오후1시까지 집에 들어오라는 말을 듣고
시계에게 후1시가 되면 알려달라고 한후 시계가 1시임을 알려주자 집으로 돌아갔습니다.

일단 위에서는 시계를 사람처럼 표현했습니다.
실제로는
첫번째는 철수가 영희와 놀다가 수시로 시간을 확인한 것이고,
두번째는 오후1시로 알람을 맞추고 영희와 논것입니다.

마찬가지로 차가 고장나서 카센터에 수리를 맡기고 수시로 수리가 완료되었는지 카센터에 전화를 해서 물어보는것보다
카센터에 자신의 전화번호를 알려주고 수리가 완료되면 알려달라고 하는것이 카센터쪽이나 수리를 맡긴사람이나 양쪽모두에게 편할 것입니다.

위의 두 예처럼 어떤 정보를 원하는 쪽이 정보를 제공하는 쪽에게 반복적으로 정보를 요구(또는 확인)하는 방법보다
정보를 제공하는 쪽이 정보를 원하는 쪽에게 통보하는 것이 효율적일 것입니다.

이런 상황에서 사용하면 좋은 것이 callback함수라고 보시면 됩니다.



아래 소스는 콜백함수를 사용한 예제로
단순한 시계클래스인 Clock클래스에 void타입의 콜백함수 타입을 만들어 놨습니다.
그리고 Clock를 사용하는 쪽에서 void타입의 콜백함수(OnAlarm)함수를 만든후 해당 함수를 Clock객체에 콜백함수로 설정하였습니다.

Clock클래스에서는 1분단위로 콜백함수를 호출하도록 설정하였습니다.

코드의 전체적인 내용은 Clock시계를 켜놓은후에 1분후에 알람이 울리도록하고 알람이 울리면 일어나서 출근한다는 내용입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* Clock.h */
#include <TIME.H>
typedef void (*pfCallback)();
class CClock
{
public:
pfCallback m_cb; // 콜백함수
struct tm now; // 현재시간
int bStop; // 시계를 멈출것인가?
CClock(void);
~CClock(void);
void Start(void);
void Stop(void);
void SetCallbackFunction(pfCallback cbFunc);
};

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/* Clock.cpp */
#include "Clock.h"
#include <PROCESS.H>
#include <WINDOWS.H>
#include <STDIO.H>
void OnTimer(void* vp);
CClock::CClock(void)
{
bStop = TRUE;
m_cb = NULL;
}
CClock::~CClock(void){}
void CClock::Start(void)
{
// 시계스레드 시작
_beginthread(OnTimer,0,this);
}
void CClock::Stop(void){ bStop = TRUE; }
void CClock::SetCallbackFunction(pfCallback cbFunc){ m_cb = cbFunc; }
void OnTimer(void* vp)
{
time_t t;
CClock* p = (CClock*)vp;
// 시계를 멈추기전까지 계속 현재시간을 구한다.
while(p->bStop!=FALSE)
{
Sleep(1000);
t = time(NULL);
p->now = *localtime(&t);
// 매1분마다 콜백함수호출
if(p->now.tm_sec == 0 )
{
if(p->m_cb) p->m_cb();
}
}
}

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
32
33
/* main.cpp */
#include "Clock.h"
#include <STDIO.H>
#include <WINDOWS.H>
// 콜백함수
void OnAlarm();
int isSleeping;
int main(int argc, char* argv[])
{
CClock clock;
clock.Start();
// OnAlarm함수를 콜백함수로 설정
clock.SetCallbackFunction(OnAlarm);
isSleeping = 1;
printf("zzz...\n");
while(isSleeping)
{
Sleep(1000);
}
clock.Stop();
printf("go to work...\n");
Sleep(1000);
return 0;
}
void OnAlarm()
{
printf("wake up!!!\n");
isSleeping = 0;
}

◈ Mysql 에서 root 암호 변경하는 방법

 

1. 데이터베이스에 접속한다.

[root@sakang]# ./mysql -u root

 

2. 데이터베이스를 선택한다.

mysql> use mysql;

 

3. user 테이블을 수정한다.

mysql> update user set password = password('new_password') where user = 'root' ;

 

4. user 테이블 확인.

mysql> select user,host,password from user;
+------+--------------+-------------------------------------------+
| user | host | password |
+------+--------------+-------------------------------------------+
| root | localhost | *831C1967BEC5BA8C85AB244701C51DFD94D3B5C0 |
| root | madrid | *831C1967BEC5BA8C85AB244701C51DFD94D3B5C0 |
+------+--------------+-------------------------------------------+

5. quit 로 아웃.

6. 데이터베이스 재시작

[root@sakang]# ./mysqladmin -u root reload

 

7. 아래와 같이 입력하면 암호 입력창이 출력.

[root@sakang]# ./mysql -u root -p


※ 암호가 설정된 이후 데이터베이스를 재시작하려면 암호가 필요하다.

./mysqladmin -u root -p reload

+ Recent posts