スクリーンセーバーを作ろう!
mouget.cpp
#include    <windows.h>
#include    <stdio.h> 
#include    <scrnsave.h>
#include    <wininet.h>
#include    <olectl.h>
#include    <time.h>

#include    "resource.h"

#define    ID_TIMER    32767
#define    BASEURL     "http://homepage1.nifty.com/mou-usshisshi/"
#define    SUB3        "sub3.htm"

#define    HIMETRIC_INCH    2540    // HIMETRIC units per inch

#define    MOUAPP_NAME            "Screen Saver.もうげっと"
#define    MOUINI_NAME            "mouget.ini"

#define    MOU_KEY_DOWNLOAD    "DOWNLOAD"
#define    MOU_KEY_DIR         "DIR"
#define    MOU_KEY_IMGCNT      "ImgCnt"
#define    MOU_DLG_TITLE       "もうげっとスクリーンセーバー"

#define    MOU_FRM_GIF         "%s\\__mouget__%d.gif"
#define    MOU_FRM_FILE        "%s\\__mouget__%s"

int GetImgList() ;
int MakeWorkFile() ;
int GetImage() ;
int ReadImg() ;
void ImagePut( HWND hWnd, int x, int y ) ;
void DeleteImg() ;

char        WorkFile[1024] ;
int         ImgCnt = 0 ;
char        ImgFile[10][255];
HGLOBAL     hGlobal[10] ;
IPicture    *iPicture[10] ;
int         ImgNum = -1 ;
BOOL        Rflag = FALSE ;

int         DWflag ;


LRESULT WINAPI ScreenSaverProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    RECT rc;
    static int wx, wy;
    int x1, y1 ;
    int    sts ;
    int i ;

    switch(msg) {
        case WM_CREATE:
            GetClientRect(hWnd, &rc);
            wx = rc.right - rc.left;
            wy = rc.bottom - rc.top;
            if ( wx < 640 ) break ;

            for ( i = 0 ; i < 10 ; i++ ) {
                hGlobal[i] = NULL ;
            }
            srand((unsigned)time(NULL));

/* ini ファイルの読み込み */
            sprintf( szAppName, MOUAPP_NAME ) ;
            sprintf( szIniFile, MOUINI_NAME ) ;
            DWflag = GetPrivateProfileInt(szAppName, MOU_KEY_DOWNLOAD, 0, szIniFile);
            if ( DWflag == 1 ) {
/* ダウンロード */
                DeleteImg() ;
                sts = GetImgList() ;
                if ( sts == 0 ) {
                    MessageBox( hWnd, "ダウンロードに失敗しました。", 
                                      MOU_DLG_TITLE, MB_OK | MB_ICONSTOP ) ;
                    break;
                }
                sts = GetImage() ;
                if ( sts == 0 ) {
                    MessageBox( hWnd, "ダウンロードに失敗しました。", 
                                      MOU_DLG_TITLE, MB_OK | MB_ICONSTOP ) ;
                    break;
                }
            }
            ImgCnt = GetPrivateProfileInt(szAppName, MOU_KEY_IMGCNT, 0, szIniFile);
/* 画像を読み込み -> メモリ展開 */
            sts = ReadImg() ;
            if ( sts == 0 ) {
                MessageBox( hWnd, "画像をダウンロードしてください。",
                                  MOU_DLG_TITLE, MB_OK | MB_ICONSTOP ) ;
                break ;
            }
/* 読み込み失敗はダイアログメッセージ? */

            Rflag = TRUE ;

            SetTimer(hWnd, ID_TIMER, 1000, NULL);
            break;
        case WM_TIMER:
            x1 = rand() % (wx - 400);
            y1 = rand() % (wy - 300);
            ImgNum ++ ;
            if ( ImgNum > (ImgCnt-1) ) ImgNum = 0 ;

            ImagePut( hWnd, x1, y1 ) ; 

            break;

        case WM_DESTROY:
            KillTimer(hWnd, ID_TIMER);
            /* 領域の解放 */
            for ( i = 0 ; i < 10 ; i++ ) {
                if ( hGlobal[i] != NULL ) {
                    iPicture[i]->Release() ;
                    GlobalFree( hGlobal ) ;
                }
            }
            PostQuitMessage(0);
            return 0;
        default:
            break;
    }
    return DefScreenSaverProc(hWnd, msg, wParam, lParam);
}



BOOL WINAPI ScreenSaverConfigureDialog(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
    char szTemp[32];
    int    sts ;

    switch (msg) {
        case WM_INITDIALOG:
/* ini ファイルを読み込み */
            sprintf( szAppName, MOUAPP_NAME ) ;
            sprintf( szIniFile, MOUINI_NAME ) ;
            DWflag = GetPrivateProfileInt(szAppName, MOU_KEY_DOWNLOAD, 0, szIniFile);
            SendMessage(GetDlgItem(hDlg, IDC_ONLINE), BM_SETCHECK, DWflag, (LPARAM)0);
            return TRUE;
        case WM_COMMAND:
            switch (LOWORD(wParam)) {
                case IDOK:
/* チェックボックスの結果を ini ファイルに保存 */
                    DWflag = SendMessage(GetDlgItem(hDlg, IDC_ONLINE), 
                                               BM_GETCHECK, (WPARAM) 0, (LPARAM)0);
                    wsprintf(szTemp, "%d", DWflag);
                    WritePrivateProfileString(szAppName, MOU_KEY_DOWNLOAD, szTemp, szIniFile);
                    EndDialog(hDlg, IDOK);
                    return TRUE;
                case IDCANCEL:
                    EndDialog(hDlg, IDCANCEL);
                    return TRUE;
                case IDC_DOWNLOAD :
/* ダウンロードする */
                    DeleteImg() ;
                    sts = GetImgList() ;
                    if ( sts == 0 ) {
                        MessageBox( hDlg, "ダウンロードに失敗しました。", 
                                          MOU_DLG_TITLE, MB_OK | MB_ICONSTOP ) ;
                        break;
                    }
                    sts = GetImage() ;
                    if ( sts == 0 ) {
                        MessageBox( hDlg, "ダウンロードに失敗しました。", 
                                          MOU_DLG_TITLE, MB_OK | MB_ICONSTOP ) ;
                        break;
                    }
                    MessageBox( hDlg, "ダウンロード完了しました。", 
                                      MOU_DLG_TITLE, MB_OK | MB_ICONINFORMATION ) ;
                    return TRUE;
            }
            return FALSE;
    }
    return FALSE;
}



BOOL WINAPI RegisterDialogClasses(HANDLE hInst)
{
    return TRUE;
}



int
GetImgList()
{
    FILE    *fp ;
    char    buff[1024] ;

    if ( MakeWorkFile() == 0 ) {
        DeleteFile( WorkFile ) ;
        return( 0 ) ;
    }

    fp = fopen( WorkFile, "r" ) ;
    if ( fp == NULL ) {
        DeleteFile( WorkFile ) ;
        return( 0 ) ;
    }

    ImgCnt = 0 ;

    while( !feof( fp ) ) {
        char *pw, *pw1 ;
        char *pImg ;


        if ( fgets( buff, sizeof(buff) ,fp ) == NULL ) break ;

        if ( (pw = strstr( buff, "IMG" )) == NULL ) {
            if ( (pw = strstr( buff, "img" )) == NULL ) {
                memset( buff, 0, sizeof( buff ) ) ;
                continue ;
            }
        }

        pw1 = pw ;
        if ( (pw = strstr( pw1, "SRC" )) == NULL ) {
            if ( (pw = strstr( pw1, "src" )) == NULL ) {
                memset( buff, 0, sizeof( buff ) ) ;
                continue ;
            }
        }

        pw1 = pw ;
        if ( (pw = strstr( pw1, "=" )) == NULL ) {
                memset( buff, 0, sizeof( buff ) ) ;
                continue ;
        }

        pw1 = pw ;
        if ( (pw = strstr( pw1, "\"" )) == NULL ) {
                memset( buff, 0, sizeof( buff ) ) ;
                continue ;
        }

        pw ++ ;
        pImg = pw ;

        pw1 = pw ;
        if ( (pw = strstr( pw1, "\"" )) == NULL ) {
                memset( buff, 0, sizeof( buff ) ) ;
                continue ;
        }
        *pw = NULL ;

        if ( strstr( pImg, "mou-Logo" ) != NULL ) {
                memset( buff, 0, sizeof( buff ) ) ;
                continue ;
        }
        if ( strstr( pImg, "banner" ) != NULL ) {
                memset( buff, 0, sizeof( buff ) ) ;
                continue ;
        }

        sprintf( ImgFile[ImgCnt], "%s", pImg ) ;
        ImgCnt ++ ;
        if ( ImgCnt == 10 ) break ;
    }
    fclose(fp) ;
    DeleteFile( WorkFile ) ;


    return( 1 ) ;

}



int
MakeWorkFile()
{
    FILE *fp;
    HINTERNET hSession;
    HINTERNET hService;

    char    buff[1024] ;
    char    urlbuff[1024] ;
    char    szText[256] ;

    GetTempPath( sizeof( buff ), buff ) ;
    GetPrivateProfileString(szAppName, MOU_KEY_DIR, buff, szText, sizeof(szText), szIniFile);
    sprintf( WorkFile, MOU_FRM_FILE, szText, SUB3 ) ;
    WritePrivateProfileString(szAppName, MOU_KEY_DIR, szText, szIniFile);

    hSession = InternetOpen( "Mou", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
    if( hSession == 0){
        return( 0 ) ;
    }

    sprintf( urlbuff, "%s%s", BASEURL, SUB3 ) ;
    hService = InternetOpenUrl( hSession, urlbuff, NULL, 0, 0, 0 );
    if( hService == 0 ){
        InternetCloseHandle(hSession);
        return( 0 ) ;
    }

    if( (fp=fopen(WorkFile, "wb")) == NULL ){
        InternetCloseHandle(hSession);
        return( 0 ) ;
    }
    while( 1 ) {
        char lpBuffer[1024+1];
        DWORD dwBytesRead = 1024;
        int    i ;

        InternetReadFile( hService, lpBuffer, 1024, &dwBytesRead );
        if( dwBytesRead == 0 ) break;
        for ( i = 0; i < 1024 ; i++ ) {
            if ( lpBuffer[i] == NULL ) break ;
            if ( lpBuffer[i] == EOF ) break ;
            if ( lpBuffer[i] == 0x0a )  {
                fputc( 0x0d, fp ) ;
            }
            fputc( lpBuffer[i], fp ) ;
        }
        memset( lpBuffer, 0, 1024+1 ) ;
    }

    fclose(fp);
    InternetCloseHandle(hService);
    InternetCloseHandle(hSession);
    return( 1 ) ;

}






int
GetImage()
{
    FILE *fp;
    HINTERNET hSession;
    HINTERNET hService;

    char    buff[1024] ;
    char    urlbuff[1024] ;
    char    filebuff[1024] ;
    char szTemp[32];
    char    szText[256] ;

    int        i ;

    GetTempPath( sizeof( buff ), buff ) ;
    GetPrivateProfileString(szAppName, MOU_KEY_DIR, buff, szText, sizeof(szText), szIniFile);

    for ( i = 0 ; i < ImgCnt ;  i++ ) {
        sprintf( filebuff, MOU_FRM_GIF, szText, i ) ;

        sprintf( urlbuff, "%s%s", BASEURL, ImgFile[i] ) ;

        hSession = InternetOpen( "Mou", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
        if( hSession == 0){
            return( 0 ) ;
        }

        hService = InternetOpenUrl( hSession, urlbuff, NULL, 0, 0, 0 );
        if( hService == 0 ){
            InternetCloseHandle(hSession);
            return( 0 ) ;
        }

        if( (fp=fopen(filebuff, "wb")) == NULL ){
            InternetCloseHandle(hService);
            InternetCloseHandle(hSession);
            return( 0 ) ;
        }

        while( 1 ) {
            char lpBuffer[1024+1];
            DWORD dwBytesRead = 1024;

            InternetReadFile( hService, lpBuffer, 1024, &dwBytesRead );
            if( dwBytesRead == 0 ) break;
            fwrite( lpBuffer, dwBytesRead, 1, fp );
            memset( lpBuffer, 0, 1024+1 ) ;
        }

        fclose(fp);
        InternetCloseHandle(hService);
        InternetCloseHandle(hSession);
    }
    wsprintf(szTemp, "%d", ImgCnt);
    WritePrivateProfileString(szAppName, MOU_KEY_IMGCNT, szTemp, szIniFile);

    return( 1 ) ;
}



int
ReadImg()
{
    int        i = 0 ;
    char    buff[1024] ;
    char    filebuff[1024] ;
    char szTemp[32];
    char szText[256];

    IStream        *iStream ;
    BOOL        ret;
    DWORD        nReadByte;
    DWORD        nFileSize;
    HANDLE        hFile;

    GetTempPath( sizeof( buff ), buff ) ;
    GetPrivateProfileString(szAppName, MOU_KEY_DIR, buff, szText, sizeof(szText), szIniFile);

    while( 1 ) {
        sprintf( filebuff, MOU_FRM_GIF, szText, i ) ;

        hFile = CreateFile(filebuff, GENERIC_READ, 0, NULL,
                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

        if(hFile == INVALID_HANDLE_VALUE) {
            // 読み込み失敗
            break ;
        }

        // ファイルサイズの取得
        nFileSize = GetFileSize(hFile, NULL);
        // 読み込み用のバッファの確保
        hGlobal[i] = GlobalAlloc(GPTR, nFileSize);

        ret = ReadFile(hFile, hGlobal[i], nFileSize, &nReadByte, NULL);
        if ( ret == 0 ) {
            // 読み込み失敗
            return( 0 ) ;
        }
        CloseHandle(hFile);

        CreateStreamOnHGlobal(hGlobal[i], TRUE, &iStream);
        OleLoadPicture(iStream, nFileSize, TRUE, IID_IPicture, (LPVOID*)&iPicture[i]);
        iStream->Release() ; 
        i ++ ;
        if ( i == 10 ) break ;
    }
    if ( ImgCnt != i ) {
        ImgCnt = i ;
        wsprintf(szTemp, "%d", ImgCnt);
        WritePrivateProfileString(szAppName, MOU_KEY_IMGCNT, szTemp, szIniFile);
    }
    if ( ImgCnt == 0 ) {
        return( 0 ) ;
    }
    return( 1 ) ;
}



void
ImagePut( HWND hWnd, int x, int y ) 
{
    HDC         hDC;
    OLE_XSIZE_HIMETRIC cx;
    OLE_YSIZE_HIMETRIC cy;
    int cxPerInch ;
    int cyPerInch ;
    long        dx, dy ;

    if ( iPicture[ImgNum] != NULL ) {
        hDC = GetDC(hWnd);
        iPicture[ImgNum]->get_Width(&cx);
        iPicture[ImgNum]->get_Height(&cy);

        cxPerInch = GetDeviceCaps(hDC,LOGPIXELSX);
        cyPerInch = GetDeviceCaps(hDC,LOGPIXELSY);

        dx = MulDiv(cx,cxPerInch,HIMETRIC_INCH) ;
        dy = MulDiv(cy,cyPerInch,HIMETRIC_INCH) ;

        iPicture[ImgNum]->Render(hDC, x, y, dx, dy,  0, cy, cx, -cy, NULL); //描画
        ReleaseDC(hWnd, hDC);
    }
}





void
DeleteImg()
{
    int     i ;
    char    filebuff[1024] ;
    char    buff[1024] ;

    for ( i = 0; i < 10 ; i++ ) {
        GetTempPath( sizeof( buff ), buff ) ;
        sprintf( filebuff, MOU_FRM_GIF, buff, i ) ;
        DeleteFile( filebuff ) ;
    }
    WritePrivateProfileString(szAppName, MOU_KEY_IMGCNT, "0", szIniFile);
}
mouget.rc
//Microsoft Developer Studio generated resource script.
//
#include "windows.h"
#include "scrnsave.h"
#include "resource.h"

/////////////////////////////////////////////////////////////////////////////
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_MOU                 ICON    DISCARDABLE     "ushi5.ico"

/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

DLG_SCRNSAVECONFIGURE DIALOG DISCARDABLE  0, 0, 158, 87
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "もうげっとスクリーンセーバーβ4"
FONT 9, "MS Pゴシック"
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,71,69,40,14
    CONTROL         "常時接続",IDC_ONLINE,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,106,21,43,10
    PUSHBUTTON      "Download",IDC_DOWNLOAD,107,40,40,14
    PUSHBUTTON      "Cancel",IDCANCEL,115,69,40,14
    GROUPBOX        "設定",IDC_STATIC,100,6,54,55
    ICON            IDI_MOU,IDC_STATIC,2,3,20,21
    LTEXT           "もうげっと\nスクリーンセーバー",IDC_STATIC,30,5,67,21
    LTEXT           "Picture by もうの世界\nProgramed by\n       デジタルまるやま製作所",
                    IDC_STATIC,3,32,95,31
END
resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by mouget.rc
//
#define IDI_MOU                         101
#define IDC_ONLINE                      1000
#define IDC_DOWNLOAD                    1001

#define IDC_STATIC -1