acllib.c

/*
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////
//  ACLLib - Advanced C Lab Library
//    Ver. 2014-07
//    For Students' Lab at Zhejiang University
//    Created     2008 by Gao Yuan
//    Modified     2009 by Cui Liwei
//                    2010 by Lan Huidong
//    Revised        2012 by Li Rui
//  Modified  2014 by Weng Kai for MOOC
////////////////////////////////////////////////////////////////

#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NON_CONFORMING_SWPRINTFS

#define CINTERFACE

#ifdef _UNICODE
#undef _UNICODE
#endif
#ifdef UNICODE
#undef UNICODE
#endif

#include "acllib.h"

#include <windows.h>
#include <olectl.h>
#include <stdio.h>
#include <stdlib.h>

#ifdef _MSC_VER
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"msimg32.lib")
#endif

#ifdef _DEBUG
#define ACL_ASSERT(_Expression,errStr) (void)( (!!(_Expression)) || (acl_error(errStr),0) )
#else
#define ACL_ASSERT(flag,errStr) ((void)0)
#endif

#define ACL_ASSERT_HWND ACL_ASSERT(g_hWnd!=0, \
    "You should call function \"initWindow(...)\" befor use function \"" __FUNCTION__ "\"" )
#define ACL_ASSERT_BEGIN_PAINT ACL_ASSERT(g_hmemdc!=0, \
    "You should call function \"beginPaint()\" befor use function \"" __FUNCTION__ "\"" )

// f
int Setup(void);

const char g_wndClassName[] = "ACL_WND_CLASS";
const char g_libName[] = "ACLLIB";

HINSTANCE g_hInstance;

HWND g_hWnd = NULL;
HDC g_hmemdc = NULL;
HBITMAP g_hbitmap = NULL;

int g_wndHeight;
int g_wndWidth;

HPEN g_pen = NULL;
ACL_Color g_penColor = BLACK;
int g_penWidth = 1;
int g_penStyle = PEN_STYLE_SOLID;

HBRUSH g_brush = NULL;
ACL_Color g_brushColor = BLACK;
int g_brushStyle = BRUSH_STYLE_SOLID;

HFONT g_font = NULL;
char g_fontName[256] = "宋体";
int g_textSize = 12;
ACL_Color g_textColor = BLACK;
ACL_Color g_textBkColor = WHITE;

int g_caretHeight = 12;
int g_caretWidth = 6;
int g_caretX = 0;
int g_caretY = 0;

int g_soundID = 0;

KeyboardEventCallback g_keyboard = NULL;
MouseEventCallback g_mouse = NULL;
TimerEventCallback g_timer = NULL;
CharEventCallback g_char = NULL;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

//
void acl_error(char *errStr)
{
    MessageBoxA(g_hWnd,errStr,g_libName,MB_ICONERROR);
    exit(0);
}

//
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    MSG          msg;
    WNDCLASSA     wndclass;
    
    g_hInstance = hInstance;
    g_hWnd = NULL;
    g_keyboard = NULL;
    g_mouse = NULL;
    g_timer = NULL;

    wndclass.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
    wndclass.lpfnWndProc   = WndProc;
    wndclass.cbClsExtra    = 0;
    wndclass.cbWndExtra    = 0;
    wndclass.hInstance     = hInstance;
    wndclass.hInstance     = hInstance;
    wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION);
    wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH);
    wndclass.lpszMenuName  = NULL;
    wndclass.lpszClassName = g_wndClassName;

    if (!RegisterClassA(&wndclass))
    {
        MessageBoxA(NULL, "This program requires Windows NT!", g_libName, MB_ICONERROR);
        return 0;
    }

    Setup();

    ACL_ASSERT(g_hWnd,"You must call \"initWindow(...)\" in Main()");

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage (&msg);
        DispatchMessage (&msg);
    }
    return msg.wParam;
}

//
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{ 
    switch (message) 
    {
    case WM_CREATE:
        {
            HDC hdc;
            hdc = GetDC(hwnd);
            g_hbitmap = CreateCompatibleBitmap(
                hdc, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
            g_hmemdc = CreateCompatibleDC(hdc);
            SelectObject(g_hmemdc, g_hbitmap);
            BitBlt(g_hmemdc, 
                0, 0, 
                GetSystemMetrics(SM_CXSCREEN),
                GetSystemMetrics(SM_CYSCREEN), 
                g_hmemdc, 
                0, 0, 
                WHITENESS);
            DeleteDC(g_hmemdc);
            ReleaseDC(hwnd, hdc);

            CreateCaret(hwnd,0,g_caretWidth,g_caretHeight);
            g_caretX = g_wndWidth;
            g_caretY = g_wndHeight;
            SetCaretPos(g_caretX,g_caretY);

            break;
        }
    case WM_ERASEBKGND:
        break;
    case WM_PAINT:
        {
            HDC hdc;
            PAINTSTRUCT ps;
            RECT rect;
            
            hdc = BeginPaint(hwnd, &ps);
            g_hmemdc = CreateCompatibleDC(hdc);
            SelectObject(g_hmemdc, g_hbitmap);
            GetClientRect(hwnd,&rect);
            BitBlt(hdc, 0, 0, rect.right - rect.left,
                rect.bottom - rect.top, g_hmemdc, 0, 0, SRCCOPY);
            DeleteDC(g_hmemdc);
            g_hmemdc = 0;
            EndPaint(hwnd,&ps);
            break;
        }
    case WM_CHAR:
        if (g_char != NULL)
            g_char((char) wParam);
        break;

    case WM_KEYDOWN:
        if (g_keyboard != NULL)
            g_keyboard((int) wParam,KEY_DOWN);
        break;

    case WM_KEYUP:
        if(g_keyboard != NULL)
            g_keyboard((int) wParam,KEY_UP);
        break;

    case WM_LBUTTONDOWN:
        if (g_mouse != NULL)
            g_mouse((int) LOWORD(lParam), (int) HIWORD(lParam), LEFT_BUTTON, BUTTON_DOWN);
        break;

    case WM_LBUTTONUP:
        if (g_mouse != NULL)
            g_mouse((int) LOWORD(lParam), (int) HIWORD(lParam), LEFT_BUTTON, BUTTON_UP);
        break;

    case WM_LBUTTONDBLCLK:
        if (g_mouse != NULL)
            g_mouse((int) LOWORD(lParam), (int) HIWORD(lParam), LEFT_BUTTON, BUTTON_DOUBLECLICK);
        break;

    case WM_MBUTTONDOWN:
        if (g_mouse != NULL)
            g_mouse((int) LOWORD(lParam), (int) HIWORD(lParam), MIDDLE_BUTTON, BUTTON_DOWN);
        break;

    case WM_MBUTTONUP:
        if (g_mouse != NULL)
            g_mouse((int) LOWORD(lParam), (int) HIWORD(lParam), MIDDLE_BUTTON, BUTTON_UP);
        break;

    case WM_MBUTTONDBLCLK:
        if (g_mouse != NULL)
            g_mouse((int) LOWORD(lParam), (int) HIWORD(lParam), MIDDLE_BUTTON, BUTTON_DOUBLECLICK);
        break;

    case WM_RBUTTONDOWN:
        if (g_mouse != NULL)
            g_mouse((int) LOWORD(lParam), (int) HIWORD(lParam), RIGHT_BUTTON, BUTTON_DOWN);
        break;

    case WM_RBUTTONUP:
        if (g_mouse != NULL)
            g_mouse((int) LOWORD(lParam), (int) HIWORD(lParam), RIGHT_BUTTON, BUTTON_UP);
        break;

    case WM_RBUTTONDBLCLK:
        if (g_mouse != NULL)
            g_mouse((int) LOWORD(lParam), (int) HIWORD(lParam), RIGHT_BUTTON, BUTTON_DOUBLECLICK);
        break;

    case WM_MOUSEMOVE:
        if(g_mouse != NULL)
            g_mouse((int) LOWORD(lParam), (int) HIWORD(lParam), MOUSEMOVE, MOUSEMOVE);
        break;

    case WM_MOUSEWHEEL:
        if(g_mouse == NULL)
            break;
        if(HIWORD(wParam) == 120)
            g_mouse((int) LOWORD(lParam), (int) HIWORD(lParam),MIDDLE_BUTTON,ROLL_UP);
        else if(HIWORD(wParam)==65416)
            g_mouse((int) LOWORD(lParam), (int) HIWORD(lParam),MIDDLE_BUTTON,ROLL_DOWN);
        break;

    case WM_TIMER:
        if (g_timer != NULL)
            g_timer(wParam);
        break;

    case WM_DESTROY:
        DeleteObject(g_hbitmap);
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
}

//
void initWindow(const char *wndName, int x, int y, int width, int height)
{
    RECT rect;

    ACL_ASSERT(!g_hWnd,"Don't call initWindow twice");

    g_wndHeight = height;
    g_wndWidth = width;

    if(x==DEFAULT || y==DEFAULT)
        x=y=CW_USEDEFAULT;
    
    g_hWnd = CreateWindowA (
        g_wndClassName, wndName,
        WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_SIZEBOX,
        x, y, 
        width, height,
        NULL, NULL, 0, NULL) ;

    if(!g_hWnd)
    {
        MessageBoxA(NULL,"Fail to create window",g_libName,MB_ICONERROR);
        exit(0);
    }
    GetClientRect(g_hWnd,&rect);
    width += width - (rect.right-rect.left);
    height += height - (rect.bottom-rect.top);
    SetWindowPos(g_hWnd,HWND_TOP,0,0,width,height,SWP_NOMOVE);

    ShowWindow (g_hWnd,1);
    UpdateWindow (g_hWnd);
}

void initConsole(void)
{
    AllocConsole();
    freopen("CONIN$", "r+t", stdin);
    freopen("CONOUT$", "w+t", stdout);
}

void msgBox(const char title[],const char text[],int flag)
{
    ACL_ASSERT_HWND;
    MessageBoxA(g_hWnd,text,title,flag);
}


//
void updatePen();
void updateBrush();
void updateFont();

//
void beginPaint()
{
    HDC hdc;

    ACL_ASSERT_HWND;
    
    hdc = GetDC(g_hWnd);
    g_hmemdc = CreateCompatibleDC(hdc);
    SelectObject(g_hmemdc,g_hbitmap);
     
    updatePen();
    updateBrush();
    updateFont();
    setTextColor(g_textColor);
    setTextBkColor(g_textBkColor);
}

void endPaint()
{
    DeleteDC(g_hmemdc);    
    g_hmemdc = 0;
    InvalidateRect(g_hWnd,0,0);

    DeleteObject(g_pen);
    DeleteObject(g_brush);
    DeleteObject(g_font);
    g_pen = NULL;
    g_brush = NULL;
    g_font = NULL;
}

void clearDevice(void)
{
    ACL_ASSERT_BEGIN_PAINT;
    BitBlt(
        g_hmemdc, 
        0, 0, 
        GetSystemMetrics(SM_CXSCREEN), 
        GetSystemMetrics(SM_CYSCREEN) , 
        g_hmemdc, 
        0, 0,
        WHITENESS);    
}

void updatePen()
{
    if(g_pen)DeleteObject(g_pen);
    if(g_penColor==EMPTY)
        g_pen = (HPEN)GetStockObject(NULL_PEN);
    else
        g_pen = CreatePen(g_penStyle,g_penWidth,g_penColor);
    SelectObject(g_hmemdc,g_pen);
}

void updateBrush()
{
    if(g_brush)DeleteObject(g_brush);
    if(g_brushColor==EMPTY)
    {
        g_brush = (HBRUSH)GetStockObject(NULL_BRUSH);
    }
    else
    {
        if(g_brushStyle==BRUSH_STYLE_SOLID)
            g_brush = CreateSolidBrush(g_brushColor);    
        else
            g_brush = CreateHatchBrush(g_brushStyle,g_brushColor);
    }
    SelectObject(g_hmemdc,g_brush);
}

void updateFont()
{
    if(g_font)DeleteObject(g_font);
    g_font = CreateFontA(
        g_textSize,
        0,
        0,0,700,0,0,0,0,0,0,0,0,g_fontName);
    SelectObject(g_hmemdc,g_font);
}

void setPenColor(ACL_Color newColor)
{
    ACL_ASSERT_BEGIN_PAINT;
    g_penColor = newColor;    
    updatePen();
}

void setPenWidth(int width)
{
    ACL_ASSERT_BEGIN_PAINT;
    g_penWidth = width;
    updatePen();
}

void setPenStyle(ACL_Pen_Style newStyle)
{
    ACL_ASSERT_BEGIN_PAINT;

    switch(newStyle)
    {
    case PEN_STYLE_SOLID:
        g_penStyle = PS_SOLID; break;
    case PEN_STYLE_DASH:
        g_penStyle = PS_DASH; break;
    case PEN_STYLE_DOT:    
        g_penStyle = PS_DOT; break;
    case PEN_STYLE_DASHDOT:
        g_penStyle = PS_DASHDOT; break;
    case PEN_STYLE_DASHDOTDOT:    
        g_penStyle = PS_DASHDOTDOT; break;
    case PEN_STYLE_NULL:
        g_penStyle = -1;
        setPenColor(EMPTY);
        return;
    default:
        break;
    }
    updatePen();
}

void setBrushColor(ACL_Color newColor)
{
    ACL_ASSERT_BEGIN_PAINT;
    g_brushColor = newColor;
    updateBrush();
}

void setBrushStyle(ACL_Brush_Style newStyle)
{
    ACL_ASSERT_BEGIN_PAINT;
    
    switch(newStyle)
    {
    case BRUSH_STYLE_SOLID:
        g_brushStyle = BRUSH_STYLE_SOLID; break;
    case BRUSH_STYLE_HORIZONTAL:    
        g_brushStyle = HS_HORIZONTAL; break;
    case BRUSH_STYLE_VERTICAL:        
        g_brushStyle = HS_VERTICAL; break;
    case BRUSH_STYLE_FDIAGONAL:        
        g_brushStyle = HS_FDIAGONAL; break;
    case BRUSH_STYLE_BDIAGONAL:        
        g_brushStyle = HS_BDIAGONAL; break;
    case BRUSH_STYLE_CROSS:            
        g_brushStyle = HS_CROSS; break;
    case BRUSH_STYLE_DIAGCROSS:        
        g_brushStyle = HS_DIAGCROSS; break;
    case BRUSH_STYLE_NULL:
        g_brushStyle = BRUSH_STYLE_SOLID;
        setBrushColor(EMPTY);
        return;
    default:
        break;
    }
    updateBrush();
}

void setTextColor(ACL_Color color)
{
    ACL_ASSERT_BEGIN_PAINT;
    ACL_ASSERT(color!=EMPTY,"text color can not be EMPTY");
    g_textColor = color;
    SetTextColor(g_hmemdc,color);
}

void setTextBkColor(ACL_Color color)
{
    ACL_ASSERT_BEGIN_PAINT;
    g_textBkColor = color;
    if(color == EMPTY)
        SetBkMode(g_hmemdc,TRANSPARENT);
    else
    {
        SetBkMode(g_hmemdc,OPAQUE);
        SetBkColor(g_hmemdc,color);
    }    
}

void setTextSize(int size)
{
    ACL_ASSERT_BEGIN_PAINT;
    g_textSize = size;
    updateFont();
}

void setTextFont(const char *pfn)
{
    size_t len;
    ACL_ASSERT_BEGIN_PAINT;
    len = strlen(pfn);
    strcpy(g_fontName,pfn);
    updateFont();
}

void paintText(int x, int y, const char *textstring)
{    
    ACL_ASSERT_BEGIN_PAINT;
    TextOutA(g_hmemdc, x, y, textstring, strlen(textstring));
}

void putPixel(int x, int y, ACL_Color color)
{
    ACL_ASSERT_BEGIN_PAINT;
    SetPixel(g_hmemdc, x, y, color);    
}

ACL_Color getPixel(int x, int y)
{
    ACL_ASSERT_BEGIN_PAINT;
    return GetPixel(g_hmemdc, x, y);
}

int getWidth(void)
{
    RECT rect;
    GetClientRect(g_hWnd, &rect);
    return rect.right;
}

int getHeight(void)
{
    RECT rect;
    GetClientRect(g_hWnd, &rect);
    return rect.bottom;
}

int getX(void)
{
    POINT point;
    ACL_ASSERT_BEGIN_PAINT;
    GetCurrentPositionEx(g_hmemdc, &point);
    return (int) point.x;
}

int getY(void)
{
    POINT point;
    ACL_ASSERT_BEGIN_PAINT;
    GetCurrentPositionEx(g_hmemdc, &point);
    return (int) point.y;
}

void moveTo(int x, int y)
{
    ACL_ASSERT_BEGIN_PAINT;
    MoveToEx(g_hmemdc, x, y,NULL);
}

void moveRel(int dx, int dy)
{
    POINT point;    
    ACL_ASSERT_BEGIN_PAINT;
    GetCurrentPositionEx(g_hmemdc, &point);
    MoveToEx(g_hmemdc, (int) point.x + dx, (int) point.y + dy,NULL);
}

// Lines and Curves
void arc(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4)
{
    ACL_ASSERT_BEGIN_PAINT;
    Arc(g_hmemdc,x1,y1,x2,y2,x3,y3,x4,y4);
}

void line(int x0, int y0, int x1, int y1)
{
    POINT point;    
    ACL_ASSERT_BEGIN_PAINT;
    GetCurrentPositionEx(g_hmemdc, &point);
    MoveToEx(g_hmemdc, x0, y0, NULL);
    LineTo(g_hmemdc, x1, y1);
    MoveToEx(g_hmemdc,point.x,point.y,NULL);
}

void lineTo(int x, int y)
{
    ACL_ASSERT_BEGIN_PAINT;
    LineTo(g_hmemdc, x, y);
}

void lineRel(int dx, int dy)
{
    POINT point;
    ACL_ASSERT_BEGIN_PAINT;
    GetCurrentPositionEx(g_hmemdc, &point);
    LineTo(g_hmemdc, (int) point.x + dx, (int) point.y + dy);
}

void polyBezier(const POINT *lppt,int cPoints)
{
    PolyBezier(g_hmemdc,lppt,cPoints);
}

void polyLine(const POINT *lppt, int cPoints)
{
    Polyline(g_hmemdc,lppt,cPoints);
}

// Filled Shapes
void chrod(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
{
    ACL_ASSERT_BEGIN_PAINT;
    Chord(g_hmemdc,x1, y1, x2, y2, x3, y3, x4, y4);
}

void ellipse(int left,int top,int right, int bottom)
{
    ACL_ASSERT_BEGIN_PAINT;
    Ellipse(g_hmemdc,left,top,right,bottom);
}

void pie(int left, int top, int right, int bottom, int xr1, int yr1, int xr2, int yr2)
{
    ACL_ASSERT_BEGIN_PAINT;
    Pie(g_hmemdc,left,top,right,bottom,xr1,yr1,xr2,yr2);
}

void polygon(const POINT *apt,int cpt)
{
    ACL_ASSERT_BEGIN_PAINT;
    Polygon(g_hmemdc,apt,cpt);
}

void rectangle(int left,int top,int right,int bottom)
{
    ACL_ASSERT_BEGIN_PAINT;
    Rectangle(g_hmemdc,left,top,right,bottom);
}

void roundrect(int left,int top,int right,int bottom,int width,int height)
{
    ACL_ASSERT_BEGIN_PAINT;
    RoundRect(g_hmemdc,left,top,right,bottom,width,height);
}

void polyline(POINT *apt,int cpt)
{
    ACL_ASSERT_BEGIN_PAINT;
    Polyline(g_hmemdc,apt,cpt);
}


void putImage(ACL_Image *pImage, int x, int y)
{
    HDC hbitmapdc;
    ACL_ASSERT_BEGIN_PAINT;
    hbitmapdc = CreateCompatibleDC(g_hmemdc);
    SelectObject(hbitmapdc, pImage->hbitmap);
    BitBlt(g_hmemdc, x, y, pImage->width, pImage->height, hbitmapdc,0,0,SRCCOPY);
    DeleteDC(hbitmapdc);
}

void putImageScale(ACL_Image *pImage,int x,int y,int width,int height)
{
    HDC hbitmapdc;
    ACL_ASSERT_BEGIN_PAINT;
    hbitmapdc = CreateCompatibleDC(g_hmemdc);
    SelectObject(hbitmapdc, pImage->hbitmap);
    if(width == -1)width = pImage->width;
    if(height == -1)height = pImage->height;
    SetStretchBltMode(g_hmemdc,COLORONCOLOR);
    StretchBlt( g_hmemdc,x,y,width,height,hbitmapdc,0,0,pImage->width,pImage->height,SRCCOPY);
    DeleteDC(hbitmapdc);
}

void putImageTransparent(ACL_Image *pImage,int x,int y,int width,int height, ACL_Color bkColor)
{
    HDC hbitmapdc;
    ACL_ASSERT_BEGIN_PAINT;
    hbitmapdc = CreateCompatibleDC(g_hmemdc);
    SelectObject(hbitmapdc, pImage->hbitmap);
    if(width == -1)width = pImage->width;
    if(height == -1)height = pImage->height;
    //SetStretchBltMode(g_hmemdc,COLORONCOLOR);
    TransparentBlt(g_hmemdc,x,y,width,height,hbitmapdc,0,0,pImage->width,pImage->height,bkColor);
    DeleteDC(hbitmapdc);
}

void loadImage(const char *image, ACL_Image *mapbuf)
{
    HDC hmapdc;
    IPicture *ipicture;
    IStream *istream;
    DWORD filesize = 0, bytes;
    OLE_XSIZE_HIMETRIC width;
    OLE_YSIZE_HIMETRIC height;
    HANDLE file = NULL;
    HGLOBAL global = NULL;
    LPVOID data = NULL;

    ACL_ASSERT_HWND;

    file = CreateFileA(image, GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL);
    if(file == INVALID_HANDLE_VALUE)
        acl_error("Fail to load image, File not exist");
    filesize = GetFileSize(file, NULL);
    
    global = GlobalAlloc(GMEM_MOVEABLE, filesize);
    data = GlobalLock(global);
    ReadFile(file, data, filesize, &bytes, NULL);
    GlobalUnlock(global);
    CreateStreamOnHGlobal(global, TRUE, &istream);
    
    OleLoadPicture(istream, filesize, TRUE, &IID_IPicture, (LPVOID*)&ipicture);
    ipicture->lpVtbl->get_Width(ipicture, &width);
    ipicture->lpVtbl->get_Height(ipicture, &height);

    mapbuf->width = (int)(width / 26.45833333333);
    mapbuf->height = (int)(height / 26.45833333333);
    
    hmapdc = CreateCompatibleDC(GetDC(g_hWnd));
    if (mapbuf->hbitmap != NULL)
        DeleteObject(mapbuf->hbitmap);
    mapbuf->hbitmap = CreateCompatibleBitmap(GetDC(g_hWnd), mapbuf->width, mapbuf->height);
    SelectObject(hmapdc, mapbuf->hbitmap);

    ipicture->lpVtbl->Render(ipicture, hmapdc, 0, 0, mapbuf->width, mapbuf->height, 0, height, width, -height, NULL);
    ipicture->lpVtbl->Release(ipicture);
    istream->lpVtbl->Release(istream);

    DeleteDC(hmapdc);
    GlobalFree(global);
    CloseHandle(file);
} 

void freeImage(ACL_Image *mapbuf)
{
    if(mapbuf->hbitmap) return;
    DeleteObject(mapbuf->hbitmap);
    mapbuf->hbitmap = NULL;
}

void registerKeyboardEvent(KeyboardEventCallback callback)
{
    g_keyboard = callback;
}

void registerCharEvent(CharEventCallback callback)
{
    g_char = callback;
}

void registerMouseEvent(MouseEventCallback callback)
{
    g_mouse = callback;
}

void registerTimerEvent(TimerEventCallback callback)
{
    g_timer = callback;
}

void startTimer(int id,int timeinterval)
{
    SetTimer(g_hWnd, id, timeinterval, NULL);
}

void cancelTimer(int id)
{
    KillTimer(g_hWnd, id);
}

void loadSound(const char *fileName,ACL_Sound *pSound)
{
    char *cmdStr;
    int len = strlen(fileName)*sizeof(char);
    len +=64;
    cmdStr = (char*)malloc(len);
    sprintf(cmdStr,"open \"%s\" type mpegvideo alias S%d",fileName,g_soundID);
    *pSound = g_soundID;
    ++g_soundID;
    mciSendStringA(cmdStr,NULL,0,NULL);
    free(cmdStr);
}

void playSound(int sid,int repeat)
{
    char cmdStr[32];
    stopSound(sid);
    if(repeat)
        sprintf(cmdStr,"play S%d from 0 repeat",sid);
    else
        sprintf(cmdStr,"play S%d from 0",sid);
    mciSendStringA(cmdStr,NULL,0,NULL);
}

void stopSound(int sid)
{
    char cmdStr[32];
    sprintf(cmdStr,"stop S%d",sid);
    mciSendStringA(cmdStr,NULL,0,NULL);
}

void setCaretSize(int w,int h)
{
    DestroyCaret();
    CreateCaret(g_hWnd,0,w,h);
    SetCaretPos(g_caretX,g_caretY);
}

void setCaretPos(int x,int y)
{
    g_caretX = x;
    g_caretY = y;
    SetCaretPos(g_caretX,g_caretY);
}

void showCaret()
{
    ShowCaret(g_hWnd);
}

void hideCaret()
{
    HideCaret(g_hWnd);
}


int random(int num)
{
    return (rand() % num);
}


你可能感兴趣的:(acllib.c)