윈도우api 윈도우프로시저 질문

ghoflvhxj의 이미지

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	static TCHAR str[256];
	int len;
 
	switch (iMessage)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_CHAR:
		len = lstrlen(str);
		str[len] = (TCHAR)wParam;
		str[len + 1] = 0;
		SetWindowText(hWnd, TEXT("A"));
		//InvalidateRect(hWnd, NULL, FALSE);
		//return 0;	return을 생략했으니 아래 WM_PAINT case문까지 실행됨. 그러나 str이 즉시 화면에 보이지 않음.
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		TextOut(hdc, 100, 100, str, lstrlen(str));
		SetWindowText(hWnd, TEXT("B"));
		EndPaint(hWnd, &ps);
		return 0;
	}
 
	//SetWindowText(hWnd, TEXT("B")); 에러 발생...!
 
	return DefWindowProc(hWnd, iMessage, wParam, lParam);
}

최근에 윈도우api 공부를 시작했는데요 아직은 잘 모르고 어려워 질문하러 찾아오게 됬습니다. 껄껄
위 코드는 키보드로 입력한 것을 윈도우에 출력하는 예제의 윈도우 프로시저 부분입니다.

질문1.
설명에서 키보드 입력을 하면 WM_CHAR 메시지가 발생하고, 입력한 것을 문자열에 축적하는 형식으로 저장한 다음
InvalidateRect 함수를 호출하면 WM_PAINT메시지를 강제로 발생시킨다고 되어있습니다.
그래서 굳이 InvalidateRect함수를 호출하지 않고 return 부분을 주석처리해서 WM_PAINT부분 까지 실행되게 하면 되는 것이 아닌가 생각해서 해봤는데 안되네요. 왜 안되는지 궁금합니다.

질문2.
디버깅용으로 SetWindowText함수로 타이틀바에 출력한다고 보았는데
switch문 밖에서 사용하니 에러(0xC000041D: 사용자 콜백 중 처리되지 않은 예외가 발생했습니다.) 가 뜨는데 왜 뜨는 걸까요?

이상한 질문 봐주셔서 감사합니다

shint의 이미지

- WndProc() 반환값은 처리 결과이며. 전송 된 메시지에 따라 다릅니다.
- 윈도우에는 ClientDC 영역과 WindowsDC() 영역이 있습니다.
- 오류 코드를 구글과 MSDN 에서 검색하여 확인해보시기 바랍니다.
HWND 핸들이 안전한지. NULL 로 초기화 후에. 비교하기도 합니다.
HWND 핸들이 안전한지. GetSafeHwnd() 함수로 확인하기도 합니다.
- GetLastError() 로 오류의 원인을 확인 할 수 있습니다.

- 오류 디버깅은 TRACE() 255자 제한'와 OutputDebugString() 를 사용합니다.
- F9 F10 F11 로 디버깅을 할 수 있습니다.

- 프로젝트 속성에서 멀티 바이트와 유니코드'를 지정해서 사용할 수 있습니다.
TCHAR 는 두가지 모두 지원
wchar 는 유니코드 지원
char 는 멀티바이트 지원

- Visual Studio 2017 Community 버전을 사용했습니다.
여기서는 HWND 오류가 발생하지 않네요. ㅇ_ㅇ;;

- MFC 와 Windows API 는 약간 다릅니다.
MFC 는 클래스 http://www.devpia.com
Windows API 는 함수 http://soen.kr

댓글 첨부 파일: 
첨부파일 크기
Package icon WindowsProject1.zip45.34 KB

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

익명 사용자의 이미지

답변1:

Quote:
InvalidateRect 함수를 호출하면 WM_PAINT메시지를 강제로 발생시킨다고 되어있습니다.

매우 간략화 된 설명입니다.
(1) InvalidateRect 함수를 호출하면, 이 API는 이름 그대로 지정된 영역(Rect)를 무효화(Invalidate) 합니다.
(2) 무효화된 영역은 소위 update region으로 누적됩니다.
(3) 어떤 윈도우의 update region이 비어 있지 않고, 해당 윈도우에 대한 메시지가 application queue에 없다면 시스템은 WM_PAINT를 생성합니다.
(4) WM_PAINT를 처리할 때, 구체적으로 BeginPaint를 호출할 때 시스템은 "실제로 다시 그려야 할 영역", 즉 update region 중에서 사용자에게 보여지는 영역만이 새로 그려지도록 합니다.

결국 InvalidateRect는 "update region"을 설정한다는 중요한 역할을 수행해야 하므로 생략되어서는 안 되는 것이죠.

더 자세한 내용은 레퍼런스를 참조하세요:
https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-invalidaterect
https://docs.microsoft.com/ko-kr/windows/desktop/api/winuser/nf-winuser-beginpaint
https://msdn.microsoft.com/en-us/library/windows/desktop/dd145137(v=vs.85).aspx

답변2:
hWnd가 어떤 값일 줄 알고, 윈도우가 어떤 상황일 줄 알고 막무가내로 SetWindowText를 호출하나요?

자세한 에러 원인은 더 분석해봐야 알겠지만 일단 매우 위험한 코드라는 느낌이 확실히 드는군요.

일단 먼저 우려되는 건, SetWindowText 자체도 메시지 메커니즘으로(해당 윈도우에 WM_SETTEXT를 보내는 식으로) 동작한다는 겁니다.

위와 같은 코드를 작성했을 때 기대할 수 있는 최상의 결과라고 해봤자 WM_SETTEXT의 무한루프라는 거죠. 무엇보다도 이러면 application queue의 메시지 수가 절대 줄어들 수가 없겠는데요?

https://msdn.microsoft.com/en-us/library/windows/desktop/ms633546(v=vs.85).aspx

첨언: 프로그래밍 공부하면서 이것저것 실험해보는 건 좋지만, 레퍼런스를 직접 찾아서 읽고 이해할 수 있는 수준이 되기 전까지는 남들이 작성한 좋은 예제들 가져다 돌려보면서 그 동작을 이해하는 데 주력하는 것이 좋습니다. 이런 corner case들에 관심 가지며 시간 쏟았다간 한 발짝 나가기도 어려울 거에요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.