설명은 따로 필요없을 것같다.
그냥 밑에 소스를 보면....

void main()

{

    int    nDec = 0;

    char szHex[16];


    // 16진수를 10진수로


    sprintf(szHex, "FF");


    nDec = (int)strtol(szHex, NULL, 16);


    printf(" %s -> %d \n", szHex, nDec);


    nDec = nDec - 0xF;


    // 10진수를 16진수로


    sprintf(szHex, "%X", nDec);


    printf("%d -> %s \n", nDec, szHex);


}



실행한 결과

 FF -> 255
240 -> F0


strtol 함수를 알면 16진수를 10진수로 바꾸는 것을 한줄에 끝낼 수 있는데
저 함수를 모르면...

sprintf의 포멧에서 %X를 쓰느냐 %x를 쓰느냐에
따라서 16진수의 영문자(A~F)가 대문자로 표시되느냐
소문자로 표시되느냐가 결정되어진다.
Posted by 띠리
CreateSemaphoreWaitForSingleObject을 이용하여
어떤 어플리케이션을 한번에 3개까지만 실행 하게하기




#include <stdio.h>

#include <windows.h>


#define SEMAPHORE_NAME "Semaphore Sample"


// 어플리케이션을 한번에 3개까지만 실행 하게

int main()

{

    HANDLE hSemaphore;

    DWORD dwResult;



    // 세마포어 만들기

    hSemaphore = CreateSemaphore(NULL, 3, 3, (LPCSTR)SEMAPHORE_NAME);


    // 지정한 오브젝트가 시그널 상태가 되

    dwResult = WaitForSingleObject(hSemaphore,    // 세마포어 오브젝트 핸들

                                   0);            // 타임아웃시간


    // 만들어진 세마포어 확인

    if(dwResult != WAIT_OBJECT_0) {

        printf("벌써 3개 실행됬어   %d\n", dwResult);

        Sleep(1000);

    } else {

        // 처리

        printf("처리시작   %d\n", dwResult);

        Sleep(10000);

        printf("처리종료   %d\n", dwResult);


        // 개방

        ReleaseSemaphore(hSemaphore, 1, NULL);

    }


    CloseHandle(hSemaphore);

    return(0);

}





vs2005용 예제 파일



프로그램을 빌드해서 실행하면 처리시작이 표시되는 프로그램은 항상 세개이다.
Posted by 띠리
플렛폼 SDK

CreateSemaphore

유명한 혹은 무명한 세마포어 오브젝트를 만들거나 Open한다.

HANDLE CreateSemaphore(
  LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // 시큐리티 기술자
  LONG lInitialCount,                          // 초기 카운트
  LONG lMaximumCount,                          // 최대 카운트
  LPCTSTR lpName                               // 오브젝트 이름
);
파라미터
lpSemaphoreAttributes

자식 프로세스가 얻은 핸들을 계승할 것인가를 결정한다.1개의 SECURITY_ATTRIBUTES 구조체에의 포인터를 지정한다.
NULL로 지정하면 자식 프로세스는 그 핸들을 계승할 수 없다.

Windows NT/2000:SECURITY_ATTRIBUTES 구조체의 lpSecurityDescriptor 멤버로 새로운 세마포어의 시큐리티 기술자를 설정한다. NULL로 지정하면 디폴트 값이 세마포에 할당된다.

lInitialCount

세마포어 오브젝트의 초기 카운트를 지정한다.
0 이상 lMaximumCount 이하의 값을 지정한다. 세마포어는 카운트가 0보다 큰 경우는 시그널 상태가 되고 카운트가 0일 경우는 비시그널 상태가 된다. 대기 함수(WaitForSingleObject 함수 등)을 사용해서 그 세마포어를 기다리고 있던 스레드를 풀어 주면 카운트가 하나 줄어든다.
ReleaseSemaphore를 사용하면 임의의 수만큼 값을 늘일 수 도 있다.
 
lMaximumCount

세마포어 오브젝트의 최대 값을 지정한다.
0보다 큰 값을 지정해야만 된다.
lpName
 
세마포어 오브젝트의 이름으로 NULL로 끝나는 문자열에 포인터를 지정한다. 이름의 최대 길이는 MAX_PATH의 길이이다. 이름을 비교할 때는 대문자와 소문자를 구별한다.

lpName 파라미터로 지정한 이름이 기존의 세마포어 오브젝트의 이름과 같을 경우,  이 함수를 실행하기위해서는 기존의 오브젝트에 대해서 SEMAPHORE_ALL_ACCESS 엑세스권이 필요한다. 이 경우, lInitialCount 파라미터와 lMaximumCount 파라미터는 오브젝트를 작성한 프로세스에 의해서 이미 설정되어 있기 때문에 무시한다. 또 lpSemaphoreAttributes 파라미터가 NULL이 아닐 경우, 자식 프로세스 핸들을 계승할 것인지를 지정하는 것은 유효하지만 시큐리티 기술자의 멤버는 무시된다.

lpName 파라미터로 NULL 을 지정하면 무명한 세마포어 오브젝트가 만들어진다.

lpName 파라미터로 지정한 이름이 기존의 이벤트, 뮤텍스, 대기 가능한 타이머, 잡, 파일 매핑 오브젝트중에 어떤 것과 같으면 이 함수는 실패하고 GetLastError함수는 ERROR_INVALID_HANDLE을 반환한다. 이것들의 오브젝트는 이름을 저장하는 공간을 공유하고 있기 때문이다.

Terminal Services:
글로벌로 이름을 저장하는 공간 또는 세션 이름을 저장하는 공간으로 오브젝트를 명시적으로 만들기 위해서는「Global\」혹은「Local\」의 prefix를 붙일 수 있다. 이름의 나머지 부분은 원기호(\)를 뺀 임의의 문자를 기술할 수 있다. 상세한 내용은 MSDN 라이브러리 「Kernel Object Name Spaces」를 참조

Windows 2000:Terminal Services가 동작하지 않는 Windows 2000 시스템에서는
「Global\」와「Local\」의 각 prefix는 무시된다.
이름의 나머지 부분은 원기호(\)를 뺀 임의의 문자를 기술할 수 있다.

Windows NT 4.0 이전과 Windows 95/98:이름의 원기호(\)를 뺀 임의의 문자를 기술할 수 있다.

반환값

함수가 성공하면 세마포오 오브젝트의 핸들을 돌려준다.
지정한 세마포어 오브젝트가 이미 존재하고 있는 경우도 이 오브젝트의 핸들을 돌려준다.
이 때 GetLastError함수는 ERROR_ALREADY_EXISTS를 돌려준다.

함수가 실패하면 NULL이 돌아오고 확장 에러 정보를 얻으려면 GetLastError함수를 사용한다.

해설

CreateSemaphore 함수가 돌려주는 핸들에는 새로운 세마포어 오브젝트에의 SEMAPHORE_ALL_ACCESS권이 할당되어져 세마포어 오브젝트의 핸들을 요구하는 임의의 함수로 사용할 수 있다.

호출하는 쪽 프로세스의 임의의 스레드는「wait functions」(대기함수)를 호출할 때에 세마포어 오브젝트의 핸들을 지정할 수 있다. 단일 오브젝트의 대기함수는 지정된 오브젝트가 시그널 상태가 되면 대기 상태에서 빠져나온다. 복수 오브젝트의 대기함수에 대해서는 지정된 오브젝트의 하나(혹은 모든것)이 시그널 상태가 되었을 때에 대기 상태에서 빠져나오도록 지시할 수 있다. 대기함수가 제어권을 돌려주면(대기 상태에서 빠져나오면) 대기중인 스레드가 풀려서 실행기 계속되어진다.

세마포어 오브젝트는 카운트가 0보다 큰 경우는 시그널 상태이고 카운트가 0의 경우는 비시그널 상태가 된다. 대기함수를 사용하여 세마포어를 기다리고 있던 스레드를 풀어주면 카운트가 하나 줄어든다. ReleaseSemaphore 함수를 사용하면 임의의 수만큼 늘일 수 있다. 카운트가 마이너스가 되거나 lMaximumCount 파라미터로 지정한 값보다 커지는 경우는 없다.

복수의 프로세스는 같은 세마포어 오브젝트의 핸들을 할당하여 프로세스간 동기의 목적으로 그 오브젝트를 사용할 수 있다. 다음과 같은 오브젝트 공유 메커니즘을 이용할 수 있다.

CreateSemaphore 함수의 lpSemaphoreAttributes 파라미터로 계승을 유효하게 해두면 CreateProcess함수가 만든 자식 프로세스는 세마포어 오브젝트 핸들을 계승할 수 있다.

•프로세스는 특정 이벤트 오브젝트의 핸들을 지정한 DuplicateHandle 함수를 호출함으로 핸들을 복사할 수 있다. 다른 프로세스는 그 핸들을 사용할 수 있다.

•프로세스는 OpenSemaphore 또는 CreateSemaphore 함수를 호출할 때 이벤트 오브젝트의 이름을 지정할 수 있다.

핸들을 닫을 때는 CloseHandle 함수를 사용한다. 프로세스가 종료될 때에 시스쳄은 그 프로세스가 가지고 있는 핸들을 자동적으로 닫는다. 세마포어 오브젝트에 대해서 하나나 또는 복수의 핸들이 열려있는 경우, 마지막 핸들이 닫힌 시점에서 그 세마포어 오브젝트가 파기되어진다.

대응정보

Windows NT/2000:Windows NT 3.1 이후
Windows 95/98:Windows 95 이후
해더:Winbase.h 안에 선언、Windows.h 을 include
임포트 라이브러리:Kernel32.lib 을 사용
Unicode:Windows NT/2000 は Unicode 판과 ANSI 판을 실장


http://msdn2.microsoft.com/en-us/library/ms682438.aspx

Posted by 띠리
플렛폼 SDK

커뮤티케이션

커뮤니케이션의 함수 일람


함수 설명
BuildCommDCB 지정한 DCB구조체에 디바이스 제어 문자열로 지정한 값을 저장한다.
BuildCommDCBAndTimeouts 디바이스 정의 문자열을 다비아스 제어 블럭 코드에 변환한 후, 디바이스 제어 블럭에 저장한다.
ClearCommBreak 지정한 통신 디바이스의 회선이 끊긴 상태를 해제하고 문자 송신을 다시 시작한다.
ClearCommError 통신 에러의 정보를 얻고 통신 디비이스의 현재 상태를 통지한다.
CommConfigDialog 드라이버가 제공하는 설정 다이얼로그 박스를 표시한다.
EscapeCommFunction 지정한 통신 디바이스에 확장 기능을 실행하도록 지시한다.
GetCommConfig 통신 디바이스의 현재 구성을 얻는다.
GetCommMask 지정한 통신 디바이스의 이벤트 마스트의 값을 얻는다.
GetCommModemStatus 모뎀의 제어 레지스터 값을 얻는다.
GetCommProperties 지정한 통신 디바이스의 통신 프로퍼티의 정보를 버퍼에 넣는다.
GetCommState 지정한 통신 디바이스의 현재의 제어 설정을 디바이스 제어 블럭(DCB구조체)에 저장한다.
GetCommTimeouts 지정한 통신 디바이스로 실행 되는 모든 읽고 쓰는 조작의 타임아웃 파라미터를 얻는다.
GetDefaultCommConfig 통신 디바이스의 초기 설정의 구성을 얻는다.
PurgeComm 지정한 통신 자원의 출력 버퍼 또는 입력 버퍼에 있는 모든 문자를 파기한다.
SetCommBreak 지정한 통신 디바이스의 문자송신을 중단하고ClearCommBreak함수가 호출 되어질때 까지 송신 회선을 절단 상태로 한다.
SetCommConfig 통신 디바이스의 현재의 구성을 설정한다.
SetCommMask 특정 통신 디바이스로 감시하는 일련의 이벤트를 설정한다.
SetCommState 디바이스 제어 블럭(DCB구조체)의 지정에 따라서 통신 디바이스를 구성한다.
SetCommTimeouts 지정한 통신 디바이스로 실행되는 모든 읽기 쓰기 조작의 타임아웃을 설정한다.
SetDefaultCommConfig 통신 디바이스의 기본 설정의 구성을 설정한다.
SetupComm 지정한 통신 디바이스의 통신 파라미터를 초기화한다.
TransmitCommChar 지정한 통신 디바이스의 출력 버퍼에 있는 미처리 데이터보다 전에 특정 문자를 송신한다.
WaitCommEvent 지정한 통신 디바이스에서 이벤트가 발생하는 것을 대기한다.
위 링크는 일본 MSDN의 설명이 링크되어 있음

http://msdn2.microsoft.com/en-us/library/aa363194.aspx

위 함수 일람의 영어 설명은 위에 사이트에 기술되어져 있음
Posted by 띠리

플랫폼 SDK Windows의 동기/비동기 관련 함수


함수 설명
CancelWaitableTimer 지정한 "대기가능" 타이버를 엑티브가 아닌 상태로 설정한다.
ChangeTimerQueueTimer CreateTimerQueueTimer 함수로 작성한 타이머 큐 타이머를 갱신한다.
CreateEvent 유명(有名:이름이 있는 or 이름이 붙어있는)하거나 무명(無名:이름이 없는 or 이름이 붙어있지않은)한 이벤트 오브젝트를 만들거나 오픈한다.
CreateMutex 유명하거나 무명한 뮤텍스 (mutually exclusive;상호배타) 오브젝트를 만들거나 오픈한다.
CreateSemaphore 유명하거나 무명한 세마포어 오브젝트를 만들거나 오픈한다.
CreateTimerQueue 타이머 큐를 만든다. 타이머 큐는 지정한 시간에 콜백 함수를 호출하기위한 가벼운 오브젝트이다.
CreateTimerQueueTimer 타이머 큐 타이머를 만든다. 이 타이머는 지정한 시간이 경과되면 시그널 상태로 된다.
CreateWaitableTimer “대기가능” 타이머 오브젝트를 만든다.
DeleteCriticalSection 소유하지않은 크리티컬 섹션 오브젝트를 지정하여, 그 오브젝트를 사용하고 있는 모든 리소스를 풀어준다.
DeleteTimerQueueEx 타이머 큐를 삭제한다. 큐에 남아있는 처리되지않은 타이머는 취소되고 삭제된다.
DeleteTimerQueueTimer 타이머 큐 타이머를 취소한다.
EnterCriticalSection 지정된 크리티컬 섹션 오브젝트의 소유권을 얻을때 까지 대기한다.
GetOverlappedResult 지정한 파일, 유명한 파이프, 통신 디바이스에 관한 오버랩(비동기) 조작의 결과를 반환한다.
InitializeCriticalSection 지정한 크리티컬 섹션 오브젝트를 초기화한다.
InitializeCriticalSectionAndSpinCount 크리티컬 섹선 오브젝트를 초기화하고 크리티컬 섹션의 스핀 카운터를 설정한다.
InterlockedCompareExchange 파라미터 Destination Comperand 로 지정한 값의 원자비교를 하여 비교 결과를 바탕으로 값을 바꾼다.
InterlockedCompareExchangePointer Destination 파라미터와 Comperand  파라미터로 지정한 값을 비교한다. 비교결과에 따라서 2개의 겂을 바꾼다.
InterlockedDecrement 지정한 변수의 값을 1씩 감소시킨다. 그 결과 얻어진 값을 체크한다.
InterlockedExchange 지정된 1개의 변수의 내용과 다른 하나의 값의 교환을 일괄처리한다.
InterlockedExchangeAdd 수를 더하는 변수에 증감한 값의 원자 가산을 한다.
InterlockedExchangePointer 지정한 두개의 값을 바꾼다.
InterlockedIncrement 지정된 변수의 값은 1씩 증가시킨다. 그 결과 얻어진 값을 체크한다.
LeaveCriticalSection 지정된 크리티컬 섹션 오브젝트의 소유권을 풀어준다.
MsgWaitForMultipleObjects 다음의 한 조건이 만족되면 제어를 돌려준다.
MsgWaitForMultipleObjectsEx 다음의 한 조건이 만족되면 제어를 돌려준다.
OpenEvent 기존의 유명한 이벤트 오브젝트를 오픈한다.
OpenMutex 지존의 유명한 뮤텍스 오브젝트를 오픈한다.
OpenSemaphore 기존의 유명한 세마포어 오브젝트를 오픈한다.
OpenWaitableTimer 기존의 유명한 "대기가능" 타이머 오브젝트의 핸들을 얻는다.
PulseEvent 지정된 이벤트 오브젝트를 시그널 상태로 설정하고 대기 스래드가 있는 경우는 적절한 수의 스레드를 풀어주고, 그 후에 이벤트 오브젝트를 비시그널 상태로 돌려놓는다.
QueueUserAPC 유저 모드 비동기 프로시져 호출(APC) 오브젝트를 지정한 스레트의 APC큐에 추가한다.
RegisterWaitForSingleObject 지정한 콜백 함수를 스레드 풀의 큐에 넣는다.
ReleaseMutex 지정한 뮤텍스(mutually exclusive ; 상호배타) 오브젝트의 소유권을 풀어준다.
ReleaseSemaphore 지정한 세마포어 오브젝트의 카운터를 지정한 수 만큼 증가시킨다.
ResetEvent 지정한 이벤트 오브젝트를 비시그널 상태로 설정한다.
SetCriticalSectionSpinCount 지정한 크리티컬 섹션의 스핀 카운터를 설정한다.
SetEvent 지정된 오브젝트를 시그널 상태로 설정한다.
SetWaitableTimer 지정한 "대기가능" 타이머를 엑티브로 한다.
SignalObjectAndWait 오브젝트의 통지와 다른 오브젝트의 대기를 원자적으로 갈 수 있다.
TimerAPCProc 어플리케이션 정의의 타이머 완료 루틴이다.
CreateWaitableTimer 함수를 호출하고 그 함수의 어드레스를 지정한다.
TryEnterCriticalSection 크리티컬 섹션의 엔트르를 막지않고 테스트한다.
UnregisterWaitEx RegisterWaitForSingleObject 함수에 의해 발행된 등록이 된 대기 동작을 취소한다.
WaitForMultipleObjects 지정된 오브젝트의 한 개 또는 모든 것이 시그널 상태로 되거나 또는 타임아웃 시간에 경과하면 제어를 돌려준다.
WaitForMultipleObjectsEx 지정된 오브젝트의 한 개 또는 모든 것이 시그널 상태가 되거나 I/O 완료 루틴 또는 APC가 스레트의 큐에 놓여졌거나 또는 타임아웃 시간이 경과하면 제어를 돌려준다.
WaitForSingleObject 지정한 오브젝트가 시그널 상태가 되거나 또는 타임아웃 시간이 경과하면 제어를 돌려준다.
WaitForSingleObjectEx 지정한 오브젝트가 시그널 상태가 되거나  I/O 완료 루틴 또는 APC가 스레트의 큐에 놓여졌거나 또는 타임아웃 시간이 경과하면 제어를 돌려준다.
WaitOrTimerCallback 스레드의 개시 어드레스의 역할을 하는 어플리케이션 정의 함수이다.
이 어드레스는 CreateTimerQueueTimer 함수, RegisterWaitForSingleObject 함수를 호출할 때 지정한다.
Posted by 띠리
Win32 SDK로 만든 간단한 시리얼 통신 예제
한 문자 보내고 받기

컴포트가 COM1로 고정되어있음으로 테스트 할때
바꾸어 주고 다시 빌드해야됨.


// 시리얼 포트 직접 입출력


#include <Windows.h>

#include "resource.h"


BOOL CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);

DWORD RecvData(LPVOID );            // 수신 전용 스레드


HWND    hWndCopy;                    // 스레드를 위한 핸들의 카피

HANDLE    hFile;                        // 파일 핸들

int        nSwitch;


int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPreInst,

                   LPSTR lpszCmdLine, int nCmdShow)

{

    // 다이알로그 표시

    DialogBox(hInst, "DLG_COM", HWND_DESKTOP, (DLGPROC)DlgProc);


    return TRUE;

}


BOOL CALLBACK DlgProc(HWND hWnd, UINT msg,

                      WPARAM wParam, LPARAM lParam)

{

    char szBuffer[200];


    switch(msg){


    case WM_INITDIALOG:


        hWndCopy = hWnd;            // 다이알로그박스 핸들

        nSwitch = 1;


        // 컴포트 열기

        hFile = CreateFile("COM1",

                    GENERIC_READ | GENERIC_WRITE,

                    0,                // 비공유

                    0,                // 시큐리티 속성:사용안함

                    OPEN_EXISTING,    // 기존 파일 오픈

                    0, 0 );            // 속성, 템플레이트


        if(hFile == INVALID_HANDLE_VALUE)

            MessageBox(0, "컴포트 열때 에러났어", "에공", MB_OK);


        DCB                dcb;


        // 지정한 통신 디바이스의 현재 DCB 설정 얻기

        // DCB : Device Control Block 디바이스 제어 블럭

        GetCommState(hFile , &dcb);           


        // 설정을 변경할 때는 코드 추가

        //        :


        // DCB의 지정에 따라 통신 디바이스 구성

        // 하드웨어와 제어 설정 초기화

        SetCommState(hFile , &dcb);           


        wsprintf(szBuffer, "BaudRate %d : ByteSize %d", dcb.BaudRate, dcb.ByteSize);


        // 다이알로그박스 캡션에 BaudRate:ByteSize 사이즈 표시

        SetWindowText(hWnd, szBuffer);


        COMMTIMEOUTS    cTimeout;


        // 현재 설정중인 타임아웃 자료 얻기

        //GetCommTimeouts(hFile, &cTimeout);   


        cTimeout.ReadIntervalTimeout        = 1000;   

        cTimeout.ReadTotalTimeoutMultiplier  = 0;

        cTimeout.ReadTotalTimeoutConstant    = 1000;

        cTimeout.WriteTotalTimeoutMultiplier = 0;

        cTimeout.WriteTotalTimeoutConstant   = 0;


        // 지정한 통신 디바이스의 읽기쓰기 타임아웃 설정

        SetCommTimeouts(hFile, &cTimeout);


        // 수신 스래드 생성하여 스타트

        DWORD            nThreadId;


        // 시리얼 통신 데이터 수신용 스레드 생성

        CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RecvData, NULL, 0, &nThreadId);


        return TRUE;


    case WM_COMMAND:


        switch(LOWORD(wParam)){


        case ID_EDIT_SEND:       


            // 송신쪽 에디트 컨트롤이 변화할 때

            if(HIWORD(wParam) == EN_CHANGE){       


                char szSend[10];


                // 송신쪽 데이터 버퍼에서 읽어오기

                GetDlgItemText(hWnd, ID_EDIT_SEND, szBuffer, sizeof(szBuffer));   


                // 선택 문자 위치 얻기

                int nPos = (int)SendDlgItemMessage(hWnd, ID_EDIT_SEND, EM_GETSEL, 0, 0);


                // 선택 항목 개시 위치

                int nStart = LOWORD(nPos);               

                szSend[0] = szBuffer[nStart - 1];


                DWORD    nByte;


                // 한문자 송신

                WriteFile(hFile, szSend, 1, &nByte, 0);   

            }

            return TRUE;


        case IDCANCEL:


            nSwitch = 0;        // 스래드 종료용


            // 컴포트 닫기

            CloseHandle(hFile);


            // 다이알로그 닫기

            EndDialog(hWnd, 0);


            return TRUE;

        }

    }


    return FALSE;

}

// 읽어오기 전용 스레드

DWORD RecvData( VOID * dummy )                   

{

    DWORD    dwByte;

    char    szRecv[10];

    int        nRet;


    while(nSwitch){


        // 한 문자 수신

        nRet = ReadFile(hFile, szRecv, 1, &dwByte, 0);


        // ReadFile()은 성공하면 0이외를 반환, 타임아웃도 성공

        if(dwByte == 1)

        {

            SetWindowText(hWndCopy, "수신했어");


            SendDlgItemMessage(hWndCopy, ID_EDIT_RECV, WM_CHAR, szRecv[0], NULL);

        }

        else

            SetWindowText(hWndCopy, "수신 대기중");

    }

    return 0;

}




VS2005의 프로젝트로 되어있는 샘플
빌드해서 두 컴퓨터에 시리얼 케이블로 연결한후
윗 텍스트박스에 글자를 입력하면 상대방 어플리케이션에
글자가 하나씩 전송됨
invalid-file

시리얼 통신 간단 예제

Posted by 띠리
BLOG main image
프로그래밍 공부하면서 써가는 개인 노트 (따라서 여기에 씌여있는 소스의 신빙성을 보장 못함 -.-;;) 이 블로그 보면서 틀린 점이 있으면 꼬옥 알려주세요. by 띠리

공지사항

카테고리

분류 전체보기 (323)
Win32 SDK 초보 (27)
통신관련 (11)
MFC TIP (20)
C/C++ TIP (10)
개발기타 (10)
링크 (2)
견물생심 (24)
이것저것 (8)
용어메모 (3)
데이터베이스 (32)
비주얼 베이직 (10)
하드웨어 (3)
C# (42)
Xcode (3)
델파이 (82)
홈페이지 (5)
MindStorm (0)
낙서 (5)
스크래치 (0)
기타 (6)
아두이노 (1)
라즈베리파이 (2)
안드로이드 (6)
파이썬 (0)
WEB (2)
Total : 987,327
Today : 405 Yesterday : 409