続・30日でOSを作る

本の中身自体はどんどん読み進めていますが、実装は未だ4日目・・・。

土日しかできない上に、土日も忙しかったりしてあんまり進みません(´・ω・)

とりあえず32Bitモードには突入してOSのグラフィックデザインを作るところまで到達したので、どういうデザインにしようかゆっくり考えてから実装を進めようかと思ってます。

まいこそろふと系みたいなのじゃなくてまっちんとっちゅ系みたいなのにしときたい件について。(円の描画とか、立体的に透き通って見える系の絵の書き方がワカラントデス)

| | コメント (0) | トラックバック (0)

30日でOSを作る

Osharibote

今更ながら,自作OS本を買いました。

まだ数日分しか進んでませんが、やる気があるうちに突き進まないと危険なきがします。3日坊主トカネ。

流し読み程度で理解できるさハッハッハーって思っていたら全然そんなことはなく、ちゃんと考えて読まないと置いてかれる仕様なのがなかなかツライところ。

理解せずにも進めるようになっているけど、やっぱり理解してから進みたいからなぁ・・・。

そのうちスクリーンショットをうpします。

| | コメント (0) | トラックバック (0)

続・MSCommコントロールの罠

RTS/CTSを使ってないのに,RTSEnableをFalseからTrueに変更したら通信できました。

なぞすぎる。

| | コメント (0) | トラックバック (0)

MSCommコントロールの罠

VBAでシリアル通信できるものを作っていますが、OnCommイベントが起きずに困ってます。データは受信バッファにたまりまくってるのにイベントが起こらないという謎な仕様・・・。TeraTermを起動するとたまってたバッファが一気に流れ始めるのでMSCommの使い方が悪いだけだと思うけど・・・。API使ってゴリっと書いたほうが早かったかなぁ・・・。

| | コメント (1) | トラックバック (0)

Alt+Tabに出てくるウィンドウの列挙

Alt+Tabを拡張するにあたって、Alt+Tabのときに出てくるウィンドウだけを列挙したかったのだけど、EnumWindowsだと全プロセスが列挙されてしまってIMEが(゚Д゚)ウゼェェェ

調べてみたけどないみたいなので、ガリっと書きました。Alt+Tab以外のを除去するプログラム。というわけで、自分メモ用や参考にしていただければということで。お約束で毎度のことだけど、このプログラムをつかって起きた障害等に私は責任を負いません。あしからず。

BOOL CALLBACK EnumWindowsProc(HWND hWnd , LPARAM lParam) {
HWND hParent , hOwner;
LONG iWndLong , iExtLong;
TCHAR sClassName[128] , sCaption[128] , sCaptionPattern[128];
BOOL fDisabled;
RECT uRect;

// 情報の取得
//親ウィンドウ
hParent = ::GetParent( hWnd );
//オーナーウィンドウ
hOwner = ::GetWindow( hWnd , GW_OWNER );
//スタイル
iWndLong = ::GetWindowLong( hWnd , GWL_STYLE );
//拡張スタイル
iExtLong = ::GetWindowLong( hWnd , GWL_EXSTYLE );
//クラス名
::GetClassName( hWnd , sClassName , 128 );
//キャプション
::GetWindowText( hWnd , sCaption , 128 );

//Alt+Tabで表示されないものを除外する
//クラス名・キャプション名の取得ができない
if( sClassName[0] == 0 )
  return TRUE;
if( sCaption[0] == 0 )
  return TRUE;
//非表示
if( ::IsWindowVisible( hWnd ) == FALSE )
  return TRUE;
//親が存在する(デスクトップならかまわない)
if( hParent != NULL && hParent != ::GetDesktopWindow() )
  return TRUE;
//オーナーが存在しちゃう
if( hOwner != NULL )
  return TRUE;
//アプリケーションウィンドウじゃない
if( iExtLong & WS_EX_TOOLWINDOW )
  return TRUE;

TRACE("%d/[%s]/\n",g_wndnum,sCaption);
g_wndnum++;

return TRUE;
}

これをEnumWindowsから呼び出しちゃってください。g_wndnumっていうのは単に何個あるかカウントしたかっただけの大域変数です。使う前に0に初期化するといいかも。つかうなら。

| | コメント (0) | トラックバック (0)

iTunesSDKを使ってネット越しに音楽を。。。

iTunesSDKを弄って、ネット越しに音楽操作できるようなツールを開発しています。できれば音楽を送りたいけど、そこまではむりかも。PCで流れてる音をハックする方法がわからないし。

これで何が便利になるかっていうと、スピーカーにつないだミュージックマシンの画面とかキーボードとかをわざわざ使わずに作業してるマシンからiTunesの操作ができるようになるから、作業してるマシンと音楽マシンが違う人はちょっと幸せになれるかも的なアプリになる予定。VNC使えばいいじゃんとかそういうのもあるけど。曲名を常時表示できたりするのがいいかなぁと思ってもみたり。

今β版ぐらいまではできてるので、あとはバグフィックスして足りない機能を徐々に追加すればいい感じになりそう。サーバーの処理部分をプラグインで追加できるようにすれば、誰でも簡単にサーバー側の調整ができるようになるけど、そこまでするのはめんどいなぁ・・・

| | コメント (0) | トラックバック (0)

COM弄り

スマートポインタを使ってるサンプルしかなくて、Dlgを使ってるとスマートポインタ使うの難しくてスマートポインタ使わない方法でやってみて失敗しまくり(´・ω・`)

COMのいいサンプルとかないかしら(・ω・)

| | コメント (0) | トラックバック (0)

WindowsMediaPlayerSDKのサンプルスクナス(・ω・`;)

WindowsMediaPlayerのPluginを作っているんだけど、もともとSDKが英語版しかないし(まぁそれはいいけど)、何より資料が少なすぎて意味がわからん。ヘルプあるけどかゆいところに手が届かないし。

WindowsMediaPlayerのPluginはレジストリにアクセスしてるんだけど、どうアクセスしてるのかがさっぱり。おかげでプロパティページのデータをどうやって保存してるかわからんし。つーか保存できてないし(・ω・`;)

SetRegistryKey使って自前で実装(;´∀`)?

| | コメント (0) | トラックバック (0)

MFCでホットキーコントロールを使ってホットキーの登録をする

MFCのホットキーコントロールを使うとホットキーの登録をユーザに任せやすくなる。だけど、そのままAPIで登録できるわけではなくて、変換が必要になるので関数にまとめてみました。

ホットキーを登録するとWM_HOTKEYが指定したhWndのウィンドウに送られてきます。

ちなみにホットキー設定画面を出すときにはホットキーを解除しておかないと設定がおかしくなるので注意。

これを使って起こった、いかなる障害において、私は責任を負いませんのであしからず。

// hWnd: WM_HOTKEYの送り先のhWnd
// hotkeyCtrl : MFCのホットキーコントロール

BOOL HotkeyRegist( HWND hWnd , CHotKeyCtrl * hotkeyCtrl , int id)
{
  DWORD wHotKey;  // ホットキーコントロールの値
  WORD wModify;  // ホットキーコントロールでのキー修飾子
  UINT fsModifiers; // キー修飾子フラグ
  UINT vk;   // 仮想キーコード

  //MFCのホットキーコントロールから値を得る
  wHotKey = hotkeyCtrl->GetHotKey();

  // キー修飾子を得る
  wModify = (WORD)(wHotKey >> 8);

  // 特殊キーコードが違うので変換しなければならない
  fsModifiers = 0;

  // Shiftキーが押されているか
  if( wModify & HOTKEYF_SHIFT )
    fsModifiers |= MOD_SHIFT;

  // Ctrlキーが押されてるか
  if( wModify & HOTKEYF_CONTROL )
    fsModifiers |= MOD_CONTROL;

  // Altキーが押されてるか
  if( wModify & HOTKEYF_ALT )
    fsModifiers |= MOD_ALT;

  // 仮想キーコードを変換
  vk = (UINT)LOBYTE(wHotKey);

  // ホットキーを登録する
  return ::RegisterHotKey( hWnd , id , fsModifiers , vk );
}

BOOL HotKeyUnregist( HWND hWnd , int id)
{
  // ホットキーを解除する
  return ::UnregisterHotKey( hWnd , id );
}

| | コメント (0) | トラックバック (0)

再生中の曲のタイトルを・・・其の2

クリップボード経由しないようにするためにヤフーメッセンジャーの状態を単独で変更できるアプリがあればなぁって思いつつも、キー操作を自動化することで擬似的に状態をハンズフリーで変更できている。時々転送失敗してるけど。というかかなり失敗してるけど。_mntの人がそういうの作れそうだけど、どうなんだろう。自分でもやってみたけど全然うまくいかなかったし。

実はヤフーメッセにWM_STATECHANGEみたいなメッセージ送ればよかったりして(それは無いか・・・)

ヤフーメッセンジャーにプラグイン機能搭載を切望中(・ω・)

| | コメント (0) | トラックバック (0)

再生中の曲のタイトルを・・・

MSNメッセンジャーとヤフーメッセンジャーを両方使っていると、ヤフーにも再生中の曲を表示したくなって色々試してみた。最初は超無理やりな方法で半自動半手動でがんばっていたけどやっぱり自動化したいとおもってまずはメディアプレイヤーのプラグインを作成。さくっと数時間で。クリップボード経由でヤフーメッセンジャーに曲のタイトルを送るのが許せる人なら幸せに慣れるかもなWMPプラグイン。

クリップボード経由だから作業してるとうざいけど( ; ゚Д゚)

ヤフーメッセンジャもプラグインが作れれば問題ないんだけどなぁ・・・(´・ェ・`)

| | コメント (0) | トラックバック (0)

IStreamBufferSink/Source

USBカメラの映像をバッファリングしながら追っかけ再生して、しかも録画したいところを選んで録画するということをしたかったのだけれども、ずっとできなかった。

解決したのはヘルプのこの一言|-`).。oO(・・・)

現在、ストリーム バッファ エンジンは、MPEG-2 ビデオとデジタル ビデオ (DV) ソースをサポートする。

  工エエェェ(´д`)ェェエエ工工

裏を返せばMPEG2とDVだけしかサポートしていませんよ。ということ。試しにMPEG2のムービーを持ってきて使ったらできた。次にDVcamをUSBカメラの代わりに使ったらできた。サポートされてるストリームの種類がDVとMPEG-2だけとは・・・。

DVでそのままやってもいいんだけど、無圧縮なのでファイルサイズがでかくなりすぎる。かといってMPEG-2にエンコードしてたらリアルタイム性がなくなる罠。どうしたらいいんだろう|ω・`)

| | コメント (0) | トラックバック (0)

プログラムで作ったグラフを保存する方法

プログラムというよりDirectShowの話題。DirectShowをやっているとGraphEditで確かめて、プログラムにするっていうのが一般的だけど、プログラム書いておかしいかどうか確かめたりするのに、GraphEditみたいなツールで視覚的にみたい時が多い。

プログラムで作ったグラフを確認する方法として、先日紹介したAddToRotの方法があるが、もう一つ、ファイルにセーブして後からGraphEditで確認する方法もある。こっちのほうが簡単かも。

方法は、以下の関数を追加して、グラフが生きてるときに呼ぶだけ。ファイル名はフルパスで。

// SaveGraphFile グラフをgrfファイルにしてGraphEditで見えるようにする関数
// 引数
//  ファイルに保存したいグラフ : pGraph
//  保存するファイル名(フルパス): wszPath

HRESULT SaveGraphFile( IGraphBuilder *pGraph , WCHAR *wszPath )
{
    const WCHAR wszStreamName[] = L"ActiveMovieGraph";
    HRESULT hr;
    IStorage *pStorage = NULL;

    // まず,GRFファイルを保持するドキュメントファイルを作る
    hr = StgCreateDocfile( wszPath , STGM_CREATE | STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE , 0 , &pStorage );
    if( FAILED( hr ) ){
        return hr;
    }

    // 次に,保存するストリームを作る
    IStream *pStream;
    hr = pStorage->CreateStream( wszStreamName , STGM_WRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE , 0 , 0 , &pStream );
    if( FAILED( hr ) ){
        return hr;
    }

    // IPersistStream::Saveメソッドはストリームを存続できる形に変換する
    IPersistStream *pPersist = NULL;
    pGraph->QueryInterface( IID_IPersistStream , reinterpret_cast<void **>(&pPersist) );
    hr = pPersist->Save( pStream , TRUE );
    pStream->Release();
    pPersist->Release();
    if( SUCCEEDED( hr ) ){
        hr = pStorage->Commit( STGC_DEFAULT );
    }
    pStorage->Release();
    return hr;
}

| | コメント (0) | トラックバック (0)

GraphEditで自分のアプリで作ったグラフを見る

GraphEditってものすごく便利で、DirectShowのプログラムを見た目で繋いでいくだけで完成する。だけど、その後ソースを吐き出してくれないから、プロトタイプ用と思いきや、自分のアプリで作ったグラフをGraphEditの絵で見ることができる。

そのためには、まず以下の二つの関数を用意する。

HRESULT AddToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)
{
    IMoniker * pMoniker;
    IRunningObjectTable *pROT;
    if (FAILED(GetRunningObjectTable(0, &pROT))) {
        return E_FAIL;
    }
    WCHAR wsz[256];
    wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph, GetCurrentProcessId());
    HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);
    if (SUCCEEDED(hr)) {
        hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph,
            pMoniker, pdwRegister);
        pMoniker->Release();
    }
    pROT->Release();
    return hr;
}

void RemoveFromRot(DWORD pdwRegister)
{
    IRunningObjectTable *pROT;
    if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) {
        pROT->Revoke(pdwRegister);
        pROT->Release();
    }
}

そして、自分のアプリで作るグラフをCoInitializeしたら、AddToRotを呼び出す。で、アプリを終わる前にGraphをReleaseするタイミングと同じタイミングでRemoveFromRotを呼び出す。これでアプリ側の準備は完了。

ge 後はアプリを実行中に、GraphEditのコレをポチっと押すと一覧見たいのが出てくるのでそこでOKを押すとグラフエディットが起動中のアプリのグラフを読み取って表示する。

これでちゃんと動かせているかわかるのでかなり便利に使ってます。

| | コメント (0) | トラックバック (0)

Sinkグラフは完成

IStreamBufferSinkを使ってシンク側のGraphはほぼ完成。だけど、IStreamBufferSourceが全然うまくいかない。解決の糸口はなし・・・。DirectShowに関する書籍少なすぎ(・ω・`lll)

| | コメント (0) | トラックバック (0)

DirectShowのIStreamBufferSinkフィルタ

CComQIPtr<IBaseFilter> pSinkF(pSink);

これをグローバルに置いていたら実行時エラーだったΣ(‘ω‘ ;* )ローカルに置き直したら普通に通過したし・・・。QueryInterfaceまで入ってるからグローバルだと怒られるっぽい(・ω・`#)

| | コメント (0) | トラックバック (0)

録画+追っかけ再生

DirectShowを使ってやっているけど、資料がMSDNしかない。DirectShow自体の資料が少ないのに、さらにその中でもマイナーな部分になるからかなりきついなぁ・・・。やりたいことは追っかけ再生ができた後の部分なのに。

IStreamBufferSinkとIStreamBufferSourceを使えばできる模様だけど、スキル不足でサクっと作れないのが痛いところ(´・ω・`)

| | コメント (0) | トラックバック (0)

ホットキーについて

チラシの裏メモ。

BOOL RegisterHotKey(
  HWND hWnd,         // ウィンドウのハンドル
  int id,            // ホットキーの識別子
  UINT fsModifiers// キー修飾子フラグ
  UINT vk            // 仮想キーコード
);

hWndに設定されたウィンドウがホットキーの通知を受ける。idはなんかGlobalAddAtom()をつかってほげほげするとか。要調査。fsModifiersはコントロールとかALTとかシフトとかWinを選ぶところ。vkはホットキーで使うCtrl+HだとしたらHの部分の仮想キーコード。

解除には

BOOL UnregisterHotKey(
  HWND hWnd// ウィンドウのハンドル
  int id      // ホットキーの識別子
);

を使う。

| | コメント (0) | トラックバック (0)

GetAsyncKeyState

vectorで公開して窓の杜で紹介された「hMouseLimit」のバグトリ(Windows98で動作がおかしい)がやっとできると思ってソースを見ていたところ、GetAsyncKeyState関数が実は9x系では動作がおかしいとか何とか。

GetAsyncKeyState( VK_LBUTTON ) & 0x8000

でマウスクリックの判定をしているから9x系対応の関数を探すか、メインルーチンを弄って環境依存じゃなくなるようにがんばるか9X系を見捨てるか・・・。9x系でも動いてほしいけどそろそろサポート切れるらしいんだよね(・ω・ )

2005/06/05追記

ルーチン見直したら98でも動いたので単にバグだっただけな罠。もうちょっと手直ししたらvectorにアップしなおしします。

| | コメント (0) | トラックバック (0)