#include<windows.h>
#include<stdio.h>
#include<commctrl.h>
LRESULT CALLBACK WndProc(HWND hwnd,UINT iMessage,WPARAM wParam,LPARAM lParam);
//윈도우 환경에서의 스레드 함수의모양 - 외우세요
DWORD WINAPI foo(void *p)
{
HWND hPrg = (HWND)p;
//WM_LBUTTONDOWN의 복사
{
for(int i = 0 ; i < 1000; ++i)
{
SendMessage(hPrg, PBM_SETPOS,i,0); //프로세스 전진
Sleep(20);
}
}
return 0;
}
TCHAR lpszClass[] = TEXT("first");
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrev,
LPSTR lpCmdLine,
int nShowCmd)
{
AllocConsole(); // 콘솔창 생성
freopen("CONOUT$", //콘솔을
"wt", //text write모드로
stdout); //stdoutrhk 연결
MSG Message;
//1. 위도우 클래스 만들기 (10가지를 다 정확히 입력하지 않으면 화면이 뜨지 않는다.)
WNDCLASS wc; //미리정의된 10개 항목을 채우는 클래스 (WNDCLASSEX 12개 항목 10개 항목에 작은 아이콘, 구조체 크기를 포함한다.)
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH);
wc.hCursor = LoadCursor ( 0, IDC_CROSS);
wc.hIcon = LoadIcon ( 0, IDI_WINLOGO );
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc; //<~ 이부분을 자신이 만드는 함수로 바꿔줘야 한다. 메시지 함수등록
wc.lpszClassName= lpszClass;
wc.lpszMenuName = 0;
wc.style = 0;
//2. 윈도우 클래스 등록하기.
RegisterClass( & wc ); // 등록을 하는 함수도 2가지가 있다. RegisterClass와 RegisterClassEx가 있다.
//WNDCLASS로 만들었으면 RegisterClass로 등록하고 WNDCLASSEX로 만들었으면 RegisterClassEx로 등록
//3. 등록된 클래스를 사용해서 윈도우 만들기.
// typedef long HWND; // 윈도우의 번호를 담을때 사용
HWND hwnd = CreateWindowEx(0 , // 확장 윈도우 스타일
lpszClass, // 윈도우 클래스 이름
TEXT("첫시작"), // 창이름
WS_OVERLAPPEDWINDOW, // 기본 Window Styles : & ~ 연산으로 기존스타일 제거하기
// WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX
20, 20, 839, 660, // X,Y,W,H
0, // 부모 윈도우 핸들( 번호 )
0, // 메뉴 핸들( 번호 )
hInstance, // 인스턴스 핸들
0); // 생성인자.( MDI 만들때 사용 )
//4. 윈도우 보여주기
ShowWindow(hwnd, nShowCmd);
while(GetMessage(&Message,0,0,0)) //메시지 큐에 가서 메시지를 꺼내오고 가져온 메시지를 윈도우 클래스에 등록된 메세지 처리함수로 전달한다.
{
//여기서 메시지를 처리하면 부모뿐 아니라 모든 자식윈도우로 전달되는 메시지도 먼저 처리할 수 있다.
TranslateMessage(&Message);
if (Message.message == WM_SYSKEYDOWN && Message.wParam == 'X')
{
PostQuitMessage(0);
MessageBox(hwnd, "종료","질문",MB_OK);
//SendMessage(hwnd, WM_CLOSE,0,0);
continue;
}
//PreTranslateMessae(&Message);
DispatchMessage(&Message);//가져온 메시지를 윈도우 클래스에 등록된 메시지 처리함수로 전달한다.
}
//MessageBox(0, "이제 알겠죠?","물음",MB_OKCANCEL);//종료되지 않게 하기 위해
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
static HWND hPrg;
static HANDLE hThread;
switch(iMessage){
case WM_DESTROY:
PostQuitMessage(0);
return 0 ;
case WM_CREATE:
hPrg = CreateWindow(PROGRESS_CLASS,"",
WS_CHILD | WS_VISIBLE | WS_BORDER | PBS_SMOOTH,
10,10,500,30,hwnd,(HMENU)1,0,0);
//범위 : 0 - 1000 초기위치 : 0으로 초기화
SendMessage(hPrg,PBM_SETRANGE32, 0, 1000);
SendMessage(hPrg,PBM_SETPOS, 0, 0);
return 0 ;
case WM_LBUTTONDOWN:
{
/*for(int i = 0 ; i < 1000; ++i)
{
SendMessage(hPrg, PBM_SETPOS,i,0); //프로세스 전진
Sleep(50);
}*/
//새로운 스레드를 만들어서 작업을 시키고 주스레드는 최대한 빨리 메시지 루프로 돌아가서
//다음 메시지를 처리한다.
DWORD tid;
hThread = CreateThread(0,0,//TKO보안, Stack크기
foo,(void *)hPrg,//스레드로 실행할 함수, 인자
CREATE_SUSPENDED,//flag,CREATE_SUSPENDED : 만들어 져도 실행은 ㅎ하지마라.
&tid); //생성된 스레드 ID를 담을 변수
// CloseHandle(hThread); // TKO의 잠조개수를 초기에 2이다.
// 스레드 종료와 함께 즉시 파괴되도록 1 줄인다.
}
return 0;
case WM_RBUTTONDOWN:
{
static BOOL bRun = FALSE;
bRun = !bRun; //Togle
if(bRun)
ResumeThread(hThread); // 스레드 재게
else
SuspendThread(hThread); // 스레드 일시 중지
}
return 0;
}
//꺼내온 메시지를 처리하지 않은경우 -> 바드시 아래 함수를 처리한다.
return(DefWindowProc(hwnd,iMessage,wParam,lParam));
}