Monday 5 June 2017

விண்டோஸ் ஏபிஐ 32 ப்ரோக்ராம்மிங்(Win 32 API Programming)

A Simple Window

விண்டோஸ் ஏபிஐ 32 ப்ரோக்ராம்மிங் செய்வது பற்றி தெரிந்துகொள்ளலாம் என http://www.winprog.org/tutorial/ இந்த லிங்கில் படிக்க ஆரம்பித்தேன்

சற்று பார்க்க கடினமாய் இருந்தாலும்..கொஞ்சநேரத்தில் ஆர்வம் கூடியது

#include 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, int nCmdShow)
{
    MessageBox(NULL, "Goodbye, cruel world!", "Note", MB_OK);
    return 0;
}

இதனை ரன் செய்யும்பொழுது ஒரு மெசேஜ் விண்டோ தோன்றிற்று


WinMain என்பது நாம் சி லாங்குவேஜில் மெயின் பங்க்ஷன் போல, இங்கிருந்துதான் ப்ரோக்ராம் துவங்கும்

அடுத்து ஒரு சிறிய விண்டோவை உருவாக்க..சற்று நிறைய லைன் கோடிங் தேவைப்படுகிறது, சி லாங்குவேஜை விட சிறிய அளவில் அவுட்புட் வருமென கூறுகிறார்கள் பாப்போம்

#include 

const char g_szClassName[] = "myWindowClass";

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "Window Registration Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window
    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        g_szClassName,
        "The title of my window",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
        NULL, NULL, hInstance, NULL);

    if(hwnd == NULL)
    {
        MessageBox(NULL, "Window Creation Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // Step 3: The Message Loop
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

 CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, 
இந்த லைன்நில் விண்டோ சைஸ் மட்டும் சிறிது மாற்றி பார்த்தேன், அவுட்புட்டில் விண்டோவின் அளவு சற்று பெரியதாகவே வந்தது  

const char g_szClassName[] = "myWindowClass";-->விண்டோஸ் கிளாஸ் உருவாக்கம் 


அடுத்து ஒரு விண்டோ உருவாக்கி அதனை கிளிக் செய்யும்பொழுது நம்முடைய EXE யின் Absolute Path காண்பிக்குமாறு கோடிங் செய்யப்போகிறோம் 


LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}


மெசேஜ் விண்டோ கோடிங்கில் கீழ் குறிப்பிட்டுள்ள லைன்களை புகுத்திவிட்டால் போதும்  

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
   switch(msg)
   {
      case WM_LBUTTONDOWN:    // <- 0="" added="" break="" case="" default:="" defwindowproc="" destroywindow="" hwnd="" just="" lparam="" msg="" postquitmessage="" pre="" return="" stuff="" this="" we="" wm_close:="" wm_destroy:="" wparam="">

இந்த கோடை பழைய ப்ரோக்ராமுடன் இணைத்தபிறகு, ரன் செய்தால்..ஒரு விண்டோ புதிதாக தோன்றும்..அதனை கிளிக் செய்தால் exeயின் Absolute Path காட்டும் 


விண்டோஸ் ஏபிஐ 32 ப்ரோக்ராம்மிங்கில் மெசேஜ் என்றால் என்ன ?

மெசேஜ் என்பது ஒரு இன்டிஜெர் வால்யூ, 

#define WM_INITDIALOG                   0x0110

விண்டோசில் எங்கு ஒரு இடத்திலிருந்து இன்னொரு இடத்திற்கு தகவல் பரிமாற்ற தேவை இருந்தாலும் அதனை மெசேஜ் கொண்டே செயலாற்றப்படும் 

மெசேஜிற்கு இரண்டு பாராமீட்டர்கள் உள்ளது wParam மற்றும் lParam

WM_CLOSE மெசேஜ் இவ்வரிண்டையுமே பயன்படுத்தாது, அதனால் இதன் மதிப்பு 0

எ.கா: PostMessage(hwnd, WM_CLOSE, 0, 0);

ஒரு மெசேஜ் அனுப்ப PostMessage() அல்லது  SendMessage() பயன்படுத்தலாம் 

PostMessage() மெசேஜெய் மெசேஜ் க்யூவில் புகுத்திவிட்டு ரெட்டர்ன் ஆகிவிடும், அனால்  SendMessage() மெசேஜெய் நேரடியாக விண்டோவ்விற்கு செய்தியை அனுப்பிவிடும்..அந்த விண்டோ அதனை ப்ரோஸ்ஸ் செய்து முடிக்கும்வரை ரெட்டர்ன் ஆகாது 

PostMessage(hwnd, WM_CLOSE, 0, 0) இந்த மெசேஜ் கோடிங் வழியாக அனுப்புவதும் இந்த
ஐகானை கிளிக் செய்வதும் ஒரே முடிவுகளை அளிக்கும்

மெசேஜ் க்யூ என்றால் என்ன ?


மெசேஜ் க்யூ என்பது சில நேரங்களில் ஒன்றுக்கும் மேற்பட்ட மெஸ்ஸஜுகள் செயல்படுத்துவதற்காக கண்ட்ரோலுக்கு ஓரே சமயத்தில் வரும், அப்போது அதனால் உடனே அதற்கு பதிலளிலக்க முடியாமல் இருப்பதால்..வரும் அணைத்து மெஸ்ஸஜுகளையும் ஒரு வரிசையில் காக்கவைத்து ஒவ்வொன்றாக செயல்படுத்தும் உத்தி


மெசேஜ் லூப் என்றால் என்ன ?

while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
}


1. மெசேஜ் லூப்  முதலில் GetMessage() எனும் பன்க்ஷனை கால் செய்யும்.. GetMessage() மெசேஜ் க்யூவில் ஏதாவது உள்ளதா என பார்க்கும் 

1.1 ஏதாவது இருப்பின் GetMessage()  ஒரு பொசிட்டிவ் வால்யூவை மெசேஜ் லூப்பிற்கு அனுப்பும், எரர் ஏதேனும் இருப்பின் நெகடிவ் வால்யூ ரெட்டர்ன் ஆகும் 

1.2 மெசேஜ் க்யூவில் ஒன்றுமில்லையானால் மெஸேஜிற்காக காத்திருக்கும் 

2. மெசேஜ் க்யூவில் இருந்து, GetMessage() பாசிட்டிவ் வால்யூ ரெட்டர்ன் ஆனால்..அடுத்து TranslateMessage() ரன் ஆகும் 

3. அடுத்து DispatchMessage(), இது மெசஜை எந்த விண்டோவிற்குரியது என கண்டறிந்து அதற்குரிய Window Procedure ஐ கண்டறிந்து அதற்கு மெசேஜ் அனுப்பும்