WAVファイルを再生する
wavファイルを再生したいときはPlaySound()を利用する。
#include "mmsystem.h"
#pragma comment(lib,"winmm.lib")
void Test(void)
{
::PlaySound(_T("C:\\WINDOWS\\Media\\chimes.wav"),NULL,SND_FILENAME | SND_ASYNC);
}
wavファイルを再生したいときはPlaySound()を利用する。
#include "mmsystem.h"
#pragma comment(lib,"winmm.lib")
void Test(void)
{
::PlaySound(_T("C:\\WINDOWS\\Media\\chimes.wav"),NULL,SND_FILENAME | SND_ASYNC);
}
マウスカーソルを動かすにはmouse_eventを使う。この関数は引数として使う座標値がスクリーン座標ではないので、GetSystemMetricsで変換して渡す。
Test用の関数を実行すると現在位置から右斜め下に向かってマウスカーソルが勝手に移動する。
//
// マウスカーソル移動関数
//
void MoveMouse(UINT nX,UINT nY)
{
DWORD dwX;
DWORD dwY;
//スクリーン座標をmouse_event()用の座標に変換
dwX = nX * 65535 / ::GetSystemMetrics(SM_CXSCREEN);
dwY = nY * 65535 / ::GetSystemMetrics(SM_CYSCREEN);
//マウスカーソルを移動
::mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,dwX,dwY,NULL,NULL);
}
void Test(void)
{
int i;
POINT pt;
//現在のマウスカーソル位置取得
::GetCursorPos(&pt);
for(i = 0; i < 30; i++)
{
//マウス位置を右斜め下にちょっとずらす
pt.x += 10;
pt.y += 10;
//マウスカーソルを移動
MoveMouse(pt.x,pt.y);
//50ミリ秒待機
::Sleep(50);
}
}
指定したファイルがあるかどうかを調べるにはCreateFileを使ってファイルにアクセスできるかどうかを調べる方法と、今回使っているFindFirstFileで検索できるかどうかを使う方法がある。
FindFirstFileの場合は少し改良すればフォルダの存在確認にも使えるので便利だ。
//
// ファイルの存在を確認する
//
bool IsFileExist(LPCTSTR pszFile)
{
HANDLE hFind;
WIN32_FIND_DATA FindFileData;
hFind = ::FindFirstFile(pszFile,&FindFileData);
if(hFind == INVALID_HANDLE_VALUE)
return false;
::FindClose(hFind);
if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
return false; //同名のフォルダがある(ファイルではない)
return true;
}
void Test(void)
{
bool ret;
ret = IsFileExist(_T("c:\\IO.SYS"));
if(ret)
::MessageBox(NULL,_T("ファイルは存在します"),_T(""),MB_OK);
else
::MessageBox(NULL,_T("ファイルは存在しません"),_T(""),MB_OK);
}
指定されたパスがショートカットファイルやリンクファイルかどうかを調べる。
独自にファイルを開くアプリケーションを作るときは先にショートカットかどうかを調べて、ショートカットファイルであればそのリンク先を取得して開く方がいい場合もある。この手の実装漏れはリリース直前のテスト作業でも発見できないことがあるので要注意かもしれない。
#include "shobjidl.h"
#include "shellapi.h"
//
// ファイルがショートカットかどうか
//
// 正常な.lnkと.urlならtrueが返る
//
bool IsShortcut(LPCTSTR pszFile)
{
DWORD_PTR dwRet;
SHFILEINFO info;
dwRet = ::SHGetFileInfo(pszFile,0,&info, sizeof(SHFILEINFO),SHGFI_ATTRIBUTES);
if(dwRet == 0)
return false;
return (info.dwAttributes & SFGAO_LINK) ? true : false;
}
void Test(void)
{
bool ret;
ret = IsShortcut(_T("c:\\IO.SYS"));
if(ret)
::MessageBox(NULL,_T("ショートカットファイルです"),_T(""),MB_OK);
else
::MessageBox(NULL,_T("ショートカットファイルではありません"),_T(""),MB_OK);
}
ブラウザーのお気に入りを右クリックしてプロパティを見ると、そのURLを表示した回数を知ることができる。この表示回数をプログラム的に取得するにはGetUrlCacheEntryInfoを利用する。
エラーのときやURLを表示したことがなければ関数はfalseを返す。
#include "wininet.h"
#pragma comment(lib,"wininet.lib")
//
// URL表示回数の取得
//
bool GetVisitsCount(LPCTSTR pszURL,DWORD* pdwCount)
{
BOOL fRet;
BYTE* pData;
DWORD cbInfo;
LPINTERNET_CACHE_ENTRY_INFO pInfo;
if(pdwCount == NULL)
return false;
*pdwCount = 0;
cbInfo = 0;
fRet = ::GetUrlCacheEntryInfo(pszURL,NULL,&cbInfo);
if(cbInfo <= 0) //fRetはFALSEが返る
return false;
pData = new BYTE[cbInfo];
if(pData == NULL)
return false;
//データ取得
pInfo = (LPINTERNET_CACHE_ENTRY_INFO)pData;
fRet = ::GetUrlCacheEntryInfo(pszURL,pInfo,&cbInfo);
if(fRet)
*pdwCount = pInfo->dwHitRate;
delete pData;
return fRet ? true : false;
}
void Test(void)
{
bool ret;
DWORD dwCount;
TCHAR pszMessage[1024];
ret = GetVisitsCount(_T("http://www.google.co.jp/"),&dwCount);
if(ret)
{
_stprintf_s(pszMessage,1024 * sizeof(TCHAR),_T("閲覧数は %d 回です"),dwCount);
::MessageBox(NULL,pszMessage,_T(""),MB_OK);
}
else
::MessageBox(NULL,_T("取得に失敗しました"),_T(""),MB_OK);
}
最近のパソコンはほとんどがAT互換機でWindowsが動いている。ソフト開発をするときもWindowsとInternet Explorerのバージョンにさえ気を配れば問題ない。
とは言うものの今でも古いパソコンを使っているユーザーは少なからずいる。古いパソコンであってもAT互換機であれば問題が生じることはほとんどない。しかしそのようなユーザーの中にはNEC製のPC-98シリーズを使っている人もいる。
アプリケーションのパッケージに動作保証は「AT互換機のみ」と書いておくだけでなく、インストーラーなどでPC-98しりーずであることをチェックして動作保証がないことを警告しておくといいかもしれない。ちなみに古いマシンと言うとMIPSやAlpha、Power PCチップのWindowsパソコンなんてものも存在するが...これらは当時でさえユーザー数が少なかったから考えなくてもいいだろう。
//
// NEC PC-98シリーズかAT互換機かのチェック
//
bool IsNEC98(void)
{
return ((::GetKeyboardType(0) == 7) && ((::GetKeyboardType(1) & 0xff00) == 0x0d00)) ? true : false;
}
void Test(void)
{
if(IsNEC98())
::MessageBox(NULL,_T("このパソコンはNECのPC-98シリーズです"),_T(""),MB_OK);
else
::MessageBox(NULL,_T("このパソコンはNECのPC-98シリーズではありません"),_T(""),MB_OK);
}
「オプションの設定項目をiniファイルとして実行ファイルの存在するフォルダ内に保存したい」というようなときに使えるのがGetModuleFileName関数。この関数では実行ファイルへのフルパスを取得できる。しかし必要なのはフォルダ名の部分までだ。ここではフォルダ名までを取得できる関数を用意した。
依存環境:ATL#include "atlstr.h"
//
// 実行ファイルの存在するフォルダとファイル名を取得する
//
//実行ファイルが"c:\test\aaa.exe"の場合は、pstrFolderに"c:\test\"、pstrFileに"aaa.exe"が帰る
//pstrFolderの末尾は'\'になる
//
bool GetExecDir(CAtlString* pstrFolder,CAtlString* pstrFile)
{
int nLen;
errno_t err;
TCHAR pcbPath[_MAX_PATH*2]; //あまり意味はないが2倍値を利用
TCHAR pszDrive[_MAX_DRIVE];
TCHAR pszFolder[_MAX_DIR];
TCHAR pszFile[_MAX_FNAME];
TCHAR pszExtent[_MAX_EXT ];
if(pstrFolder == NULL && pstrFile == NULL)
return true;
if(pstrFolder)
*pstrFolder = _T("");
if(pstrFile)
*pstrFile = _T("");
//起動ディレクトリ名、ファイル名取得
nLen = ::GetModuleFileName(NULL,pcbPath,_MAX_PATH*2);
if(nLen == 0)
return false;
//パスの分解
err = ::_tsplitpath_s(pcbPath,pszDrive,_MAX_DRIVE,pszFolder,_MAX_DIR,pszFile,_MAX_FNAME,pszExtent,_MAX_EXT);
if(err != 0)
return false;
//結果保存
if(pstrFolder)
{
*pstrFolder = pszDrive;
*pstrFolder += pszFolder;
}
if(pstrFile)
{
*pstrFile = pszFile;
*pstrFile += pszExtent;
}
return true;
}
void Test(void)
{
CAtlString strMessage;
CAtlString strFolder;
CAtlString strExec;
GetExecDir(&strFolder,&strExec);
strMessage.Format(_T("フォルダは「%s」、ファイル名は「%s」です"),strFolder,strExec);
::MessageBox(NULL,strMessage,_T(""),MB_OK);
}
■はじめに
WTLはライセンスがCPLのオープンソースプロジェクトとして公開されている。そのためおそらく勝手に日本語化したものを配布しても問題ないと思い用意しました。ライセンス的に問題があるようでしたらお知らせください。削除します。
■メリット
従来の英語版WTLではプロジェクト作成後にリソースエディタでメニューなどの言語を日本語に切り替えて、表示文字列を編集する必要がありました。しかしこの日本語版WTL 7.5ではプロジェクト生成直後から日本語リソースが利用可能です。
■日本語化内容:
・WTL 7.5のreadme.html(の一部)
・Windowsアプリケーション用アプリケーションウィザード
・Windowsアプリケーション用アプリケーションウィザードのセットアップ
・アプリケーションウィザードによって生成されるソースコード
・アプリケーションウィザードによって生成されるソースコードのコメント
※WTL 7.5のサンプルやWindows CE用のアプリケーションウィザードは日本語化していません。また、ダウンロード可能なファイルにも含まれません。
※WTL 7.5のincldueファイルも含みますが日本語化されていません。
※短時間で翻訳処理したため変な日本語になっている部分があります。
■ダウンロード
日本語版WTL 7.5をダウンロード
■以下は画面例です




アプリケーションをインストールするときにプログラムメニューやデスクトップ上にショートカットを生成したいことがある。そのような場合はCOMインターフェースのIShellLinkを通じて作成する。ショートカットファイルの拡張子には「.lnk」を指定する。
また、この方法でURLへのショートカット作成もできるが一般的ではない。作成したい場合はIUniformResourceLocatorを利用するべきだ。
#include <shlobj.h>
//
// ショートカットの作成
//
// pszLinkにショートカットを保存します。拡張子に「.lnk」を指定してください。
// ショートカットのターゲットはpszFile、説明はpszDescription...とオプションを設定できます。
//
bool CreateShortcut(LPCTSTR pszLink,LPCTSTR pszFile,LPCTSTR pszDescription=NULL,LPCTSTR pszArgs=NULL,LPCTSTR pszWorkingDir=NULL,LPCTSTR pszIconPath=NULL,int nIcon=0,int nShowCmd=SW_SHOWNORMAL)
{
HRESULT hr;
IShellLink* pIShellLink;
IPersistFile* pIPersistFile;
//IShellLinkの作成
pIShellLink = NULL;
hr = ::CoCreateInstance(CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,IID_IShellLink,(void**)&pIShellLink);
if(pIShellLink == NULL || FAILED(hr))
return false;
//IPersistFileの取得
pIPersistFile = NULL;
hr = pIShellLink->QueryInterface(IID_IPersistFile,(void**)&pIPersistFile);
if(pIPersistFile == NULL || FAILED(hr))
{
pIShellLink->Release();
return false;
}
//ショートカット詳細設定
hr = pIShellLink->SetPath(pszFile);
if(SUCCEEDED(hr) && pszDescription)
hr = pIShellLink->SetDescription(pszDescription);
if(SUCCEEDED(hr) && pszArgs)
hr = pIShellLink->SetArguments(pszArgs);
if(SUCCEEDED(hr) && pszWorkingDir)
hr = pIShellLink->SetWorkingDirectory(pszWorkingDir);
if(SUCCEEDED(hr) && pszIconPath)
hr = pIShellLink->SetIconLocation(pszIconPath,nIcon);
if(SUCCEEDED(hr))
hr = pIShellLink->SetShowCmd(nShowCmd);
#ifndef UNICODE
WCHAR* pwszUnicode;
int nLen;
//Unicode変換
nLen = ::MultiByteToWideChar(CP_ACP,0,pszLink,-1,NULL,0);
pwszUnicode = new WCHAR[nLen + 1];
if(pwszUnicode == NULL)
{
pIPersistFile->Release();
pIShellLink->Release();
return false;
}
nLen = ::MultiByteToWideChar(CP_ACP,0,pszLink,-1,pwszUnicode,nLen + 1);
if(nLen == 0)
hr = E_FAIL;
//ショートカットの保存
if(SUCCEEDED(hr))
hr = pIPersistFile->Save(pwszUnicode,TRUE);
delete pwszUnicode;
#else
//ショートカットの保存
if(SUCCEEDED(hr))
hr = pIPersistFile->Save(pszLink,TRUE);
#endif
pIPersistFile->Release();
pIShellLink->Release();
return SUCCEEDED(hr) ? true : false;
}
void Test(void)
{
bool ret;
//COM初期化
::CoInitialize(NULL);
ret = CreateShortcut(_T("c:\\test.lnk"),_T("c:\\windows\\notepad.exe"),_T("メモ帳"));
if(ret)
::MessageBox(NULL,_T("ショートカットの作成に成功しました"),_T(""),MB_OK);
else
::MessageBox(NULL,_T("ショートカットの作成に失敗しました"),_T(""),MB_OK);
//COM開放
::CoUninitialize();
}
アプリケーションをインストールするときにお気に入りにURLを追加したいことがある。そのような場合はCOMインターフェースのIUniformResourceLocatorを通じて作成する。ショートカットファイルの拡張子には「.url」を指定する。
#include <shlobj.h>
#include <intshcut.h>
//
// URLショートカットの作成
//
// pszLinkにショートカットを保存します。拡張子に「.url」を指定してください。
//
bool CreateInternetShortcut(LPCTSTR pszFile,LPCTSTR pszURL)
{
HRESULT hr;
IPersistFile* pIPersistFile;
IUniformResourceLocator* pIUniformResourceLocator;
pIUniformResourceLocator = NULL;
hr = ::CoCreateInstance(CLSID_InternetShortcut,NULL,CLSCTX_INPROC_SERVER,IID_IUniformResourceLocator,(void**)&pIUniformResourceLocator);
if(pIUniformResourceLocator == NULL || FAILED(hr))
return false;
hr = pIUniformResourceLocator->QueryInterface(IID_IPersistFile,(void**)&pIPersistFile);
if(pIPersistFile == NULL || FAILED(hr))
{
pIUniformResourceLocator->Release();
return false;
}
hr = pIUniformResourceLocator->SetURL(pszURL,0);
#ifdef _UNICODE
if(SUCCEEDED(hr))
hr = pIPersistFile->Save(pszFile,TRUE);
#else
WCHAR* pwszUnicode;
int nLen;
//Unicode変換
nLen = ::MultiByteToWideChar(CP_ACP,0,pszFile,-1,NULL,0);
pwszUnicode = new WCHAR[nLen + 1];
if(pwszUnicode == NULL)
{
pIPersistFile->Release();
pIUniformResourceLocator->Release();
return false;
}
nLen = ::MultiByteToWideChar(CP_ACP,0,pszFile,-1,pwszUnicode,nLen + 1);
if(nLen == 0)
hr = E_FAIL;
//ショートカットの保存
if(SUCCEEDED(hr))
hr = pIPersistFile->Save(pwszUnicode,TRUE);
delete pwszUnicode;
#endif
pIPersistFile->Release();
pIUniformResourceLocator->Release();
return SUCCEEDED(hr) ? true : false;
}
void Test(void)
{
bool ret;
//COM初期化
::CoInitialize(NULL);
ret = CreateInternetShortcut(_T("c:\\test.url"),_T("http://www.google.co.jp/"));
if(ret)
::MessageBox(NULL,_T("ショートカットの作成に成功しました"),_T(""),MB_OK);
else
::MessageBox(NULL,_T("ショートカットの作成に失敗しました"),_T(""),MB_OK);
//COM開放
::CoUninitialize();
}