Microsoft Visual C++ 2008 で、恐らく最良解決な2つのListViewの同期スクロール

 System::Windows::Forms::ListViewには、2つのListViewの同期スクロール機能がありません。
 そこで、ListViewを継承してカスタムコントロールを作るわけですが、スクロールイベントを拾っても、どこかで動作がおかしかったり、うまく同期しなかったりと、腹を立てることになります。

 というわけで、Viewプロパティが、System::Windows::Forms::View::Details限定ならば、次のようなコードでうまく動作するという事例をご紹介(納品した製品でうまく動いているのでOKだと思います)。

#pragma once

#define WIN32_LEAN_AND_MEAN
#pragma comment(lib, "user32.lib")
#include <windows.h>
#include <CommCtrl.h>

using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Collections::Generic;
using namespace System::Windows::Forms;

namespace MyControls {

public ref class MyListView : public System::Windows::Forms::ListView
{
public:
	// コンストラクタ
	MyListView()
	{
		View = System::Windows::Forms::View::Details; // Details限定

		mVScrollSynchronizedListView = nullptr;

		mOldScrollY = 0;
		mSyncScroll = false;
	}

	// 垂直スクロールを同期させるリストビュー
	[CategoryAttribute("特殊")]
	[DescriptionAttribute("垂直スクロールを同期させるリストビューを指定します")]
	property MyListView^ VScrollSynchronizedListView
	{
		MyListView^ get() {
			return mVScrollSynchronizedListView;
		}
		void set(MyListView^ x) {
			mVScrollSynchronizedListView = x;
		}
	}

	// 垂直スクロールの旧位置
	[BrowsableAttribute(false)]
	property int OldScrollY
	{
		int get() {
			return mOldScrollY;
		}
		void set(int x) {
			mOldScrollY = x;
		}
	}

	// 連動スクロール開始
	[BrowsableAttribute(false)]
	property bool SyncScroll
	{
		bool get() {
			return mSyncScroll;
		}
		void set(bool x) {
			mSyncScroll = x;
		}
	}

protected:

	// 連動スクロール用イベント処理
	virtual void WndProc(Message %m) override
	{
		ListView::WndProc(m);

		if(mSyncScroll
		&& m.Msg==WM_PAINT) {
			SCROLLINFO si;
			ZeroMemory(&si,sizeof(SCROLLINFO));
			si.cbSize = sizeof(SCROLLINFO);
			si.fMask  = SIF_POS;

			if(Items->Count
			&& ::GetScrollInfo((HWND)Handle.ToPointer(),SB_VERT,&si)) {
				if(mOldScrollY!=si.nPos) {
					if(mVScrollSynchronizedListView) {
						int dx = 0;
						int dy = (si.nPos - mOldScrollY) * Items[0]->Bounds.Height;

						mVScrollSynchronizedListView->OldScrollY = si.nPos;
						::SendMessage((HWND)mVScrollSynchronizedListView->Handle.ToPointer(),LVM_SCROLL,(WPARAM)dx,(LPARAM)dy);
					}
				}
				mOldScrollY = si.nPos;
			}
		}
	}

private:

	MyListView^ mVScrollSynchronizedListView;
	bool        mSyncScroll;
	int         mOldScrollY;
};
}

 もう、描画イベントを全部キャプチャして無理矢理スクロールしてしまえということです。

 このコントロールをフォームに2つ貼り付けて…。

listView1->VScrollSynchronizedListView = listView2;
listView2->VScrollSynchronizedListView = listView1;

listView1->SyncScroll = true;
listView2->SyncScroll = true;

とすれば、listView1とlistView2の垂直スクロールが同期します。

 勿論、水平スクロールの同期もこのコードをちょっと改造すれば対応可能です。

動的URLを静的URLにリダイレクトする

 Web上に沢山載っていたのは、静的URLを動的URLにリダイレクトするというもの。

http://www.olddomain.com/optimus/prime.html

  ↓

http://www.newdomain.com/optimus.cgi?id=prime

 今回、sirmiles.comから一部コンテンツを移転するにあたり、逆パターンが突如必要になりました。

http://www.olddomain.com/optimus.cgi?id=prime

  ↓

http://www.newdomain.com/optimus/prime.html

 .htaccessを使って、次のように記述するとOK。

RewriteEngine on

RewriteCond %{QUERY_STRING} ^id=(.*)$
RewriteRule (.*)\.cgi$ http://www.newdomain.com/$1/%1.html? [R=301,L]

 RewriteCondでキャプチャしたグループが%1で参照できるとは知りませんでした(苦笑)。

Repl-Ace on .NET

 実はRepl-Aceの次期Verを開発中。

 現VerはBorland C++Builderで開発しましたが、Unicode対応やらが非常に面倒なので、今度は.NET Frameworkに乗っかります。

 でも、.NET Framework自体も結構面倒な代物です。C++/CLIは分かりやすいけれども、スレッドの扱いとかはC++Builderの方がすっきりしてて良い。

 いずれにせよ、いつになることやら。
 ようやく肝心の置換処理に入ったところです。


 新Verの目玉としては…

  1. 内部処理がSJISだった為、他の文字セットに関しては限定的対応でしたが、.NET FrameworkUnicodeベースなので、結構良くなるかと。色んな所で批判されましたからね^^;
  2. 置換シミュレーションがパワーアップ。
  3. mlang.dllを使った文字セットの自動判定(ただし、誤判定もままアリ…)。
  4. ファイル名置換、連番置換。

といったところ。

ゴーオンジャー大辞典 デザイン変更

 ゴーオンジャー大辞典。もう少しそれぞれの要素が鮮やかに分離するように変えてみました。

 ところが、IE特有の有名な「peek-a-booバグ」に悩まされまくることに。
 結局、CSSIEハックを埋めまくって解決。けど、イヤだよな、こんなの。

* html p, 
* html dl, 
* html dt, 
* html dd, 
* html ul, 
* html li, 
* html h1,  ..たくさんの要素... { height: 1%; }
*:first-child+html p, 
*:first-child+html dl, 
*:first-child+html dt, 
*:first-child+html dd, 
*:first-child+html ul, 
*:first-child+html li, 
*:first-child+html h1,  ..たくさんの要素... { height: 1%; }

 ちなみに、上段がIE6用、下段がIE7用です。

頻繁なログアウト

 MT4.1にヴァージョンアップした頃から、管理画面を遷移する度にログアウトしたり、再構築中にもログアウトされたりと、もうとんでもなくイライラな現象に悩まされましたが、解決したようです。

 Cookieを消したり色々と試行しましたが、あんまり関係ないです。

 Six Apart様やさくら様に問い合わせたりして、ご迷惑をおかけいたしましたが、結局自己解決。申し訳ございませんでした…。


 SQLiteを使っている場合、大量のトラックバックスパムを消しても、DBのサイズが巨大になっていきます。
 私の場合、当分トラックバックスパムを消し忘れており、何と15,000件たまっていました。
 まず、これをMTで消す。消しておかないと、何故か次の手順で失敗します。

 続いて、telnetでサーバにログインし、

%sqlite3 '[DBファイル名]'

とタイプ。

SQLite version 3.3.6
Enter ".help" for instructions
sqlite>

と出るので、

sqlite> vacuum;

とタイプ。これで何もメッセージが出なければ成功。

sqlite> .quit

で終了です。

 すると、DBファイルが最適化されてグッと縮小され、MTの動作が軽くなります。
 これで、頻繁ログアウト問題までついでに解決されます。


 元々ブログ自体が巨大な方は、最適化してもDBファイルのサイズが大きい可能性が高いので、この方法を試してもダメかも知れません。


 ちなみに、事前にDBファイルのバックアップは必ずとっておきましょう。

ゴーオンジャー大辞典

 ゲキレンジャーサイトに続き、ゴーオンジャーのサイトもやります!

 ゴーオンジャー大辞典

 パロディや大人向けサービス、善悪では把握できない概念など、ビジュアルに反して意外と大人向けっぽかったゲキレンジャーですが、ゴーオンジャーは潔く子供向けになっており、これはこれで非常に期待しています。

 ゴーオンジャー大辞典は、ブログ形式の色を押し出すことで読み易いサイトとし、これまで運営してきたファンサイトの辞典的側面を継承しています。

 ご期待下さい。