2013年12月17日
ListView とかの子要素があるコントロールで、子要素(メニューの一項目とか)をダブルクリックで操作したい場合があります。
これを実現するとき、単純に ListView のイベント(ListView.MouseDoubleClick) に処理を記述すると、子要素のない領域や、スクロールバーへのダブルクリックでも反応してしまい、面倒です。
これに対処するには、子要素(ListViewItem) のイベント (ListViewItem.MouseDoubleClick) に処理を書くようにします。
ただ、直接は指定できないので、Style 設定を経由して指定します。 (直接書ける方法があるかもしれないけど知らない--;)
<ListView Name="A"
ItemsSource="{Binding Items}"
Margin="0,0,0,275">
<ListView.Resources>
<Style TargetType="ListViewItem">
<EventSetter Event="MouseDoubleClick"
Handler="ListViewItem_MouseDoubleClick" />
</Style>
</ListView.Resources>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
コードビハインドの例はこんな感じ
Class MainWindow
Public Property Items As New ObjectModel.ObservableCollection(Of String)
Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
Me.DataContext = Me
Me.Items.Add("あああ")
Me.Items.Add("いいい")
Me.Items.Add("ううう")
Me.Items.Add("えええ")
End Sub
Private Sub ListViewItem_MouseDoubleClick(sender As Object, e As MouseButtonEventArgs)
Dim item = CType(sender, ListViewItem)
MsgBox(item.Content)
End Sub
End Class
posted in WPF, xaml by ooltcloud | No Comments
2013年12月16日
標準のチェックボックスではいささか小さい…という場合には、LayoutTransform に ScaleTransform を設定すると大きくできます。
<CheckBox Content="ああああ">
<CheckBox.LayoutTransform>
<ScaleTransform CenterX="0"
CenterY="0"
ScaleX="1.5"
ScaleY="1.5" />
</CheckBox.LayoutTransform>
</CheckBox>

ただ、上記の方法だと、チェックボックスのキャプション(Content) も拡大されてしまいます。キャプションは拡大したくない…という場合は、Caption は CheckBox 内に配置するのではなく、外側に TextBlock を配置することで解決します。
ついでですが、LayoutTransform に複数の変形要素を設定したい場合は、TransformGroup で囲みます。
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<CheckBox>
<CheckBox.LayoutTransform>
<TransformGroup>
<ScaleTransform CenterX="0"
CenterY="0"
ScaleX="1.5"
ScaleY="1.5" />
<RotateTransform CenterX="0"
CenterY="0"
Angle="45"/>
</TransformGroup>
</CheckBox.LayoutTransform>
</CheckBox>
<TextBlock Text="ああああ"
VerticalAlignment="Center" />
</StackPanel>
</Grid>

また、LayoutTransform と LayoutTransform の違いはここが詳しいです。
http://d.hatena.ne.jp/Yamaki/20070222/1172107092
posted in Program, xaml by ooltcloud | No Comments
2013年12月15日
DataGrid にコンボボックスやチェックボックスを配置する場合、DataGridComboBoxColumn や DataGridCheckBoxColumn を使用するのが標準的な方法です。が、これだとメニュー表示するまでに、「セルを選択」→「編集モード移行」→「メニュー表示」、と3クリックを必要とします。 # なんでこんな仕様に…(汗
初期状態

1Click 目

2Click 目

3Click 目
DataGrid の仕様として、「セルを選択の後、再度クリックすると編集モードになり、そこから…」ということのようなので、そうなるのは理解できるとしても、操作感としては「面倒」以外何物もないわけです。
チェックボックスも同様で、チェックの On/Off をするのに 2Click を必要とします。
これを「セルを選択と同時にメニューを表示したい」場合、DataGridComboBoxColumn の使用は諦めて、DataGridTemplateColumn を構成するのが近道のようです。たとえば以下のような感じ。
<DataGrid AutoGenerateColumns="False"
ItemsSource="{Binding DataGridItems}">
<DataGrid.Columns>
<!-- コンボボックス側 -->
<DataGridTemplateColumn IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox SelectedItem="{Binding Choice,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
VerticalContentAlignment="Center">
<ComboBox.Items>
<System:String>あああ</System:String>
<System:String>いいい</System:String>
<System:String>ううう</System:String>
</ComboBox.Items>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- チェックボックス側 -->
<DataGridTemplateColumn IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Check, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Center"
VerticalAlignment="Center">
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
ポイントは、Binding の際に UpdateSourceTrigger を設定してすること。
"UpdateSourceTrigger=LostFocus" でも "UpdateSourceTrigger=PropertyChanged" でもどちらでもよいですが、適切なものを設定します。
でないとデフォルトは "UpdateSourceTrigger=Explicit" 相当の動きとなってしまうようなので、"Mode=TwoWay" にしててもデータソースに更新されません。
posted in Program, WPF, xaml by ooltcloud | No Comments
2013年12月15日
DataGrid の ComboBox に固定のリストを割り当てる例。
ポイントは、DataGridComboBoxColumn には ComboBox (DataGridComboBoxColumn でない普通の ComboBox) にはある、Items プロパティがないので、直接要素が列記できなくて、Array あたりで括っておかないとならない点です。(面倒な…)
<DataGrid AutoGenerateColumns="False"
ItemsSource="{Binding DataGridItems}" >
<DataGrid.Columns>
<DataGridComboBoxColumn SelectedValueBinding="{Binding Choice}">
<DataGridComboBoxColumn.ItemsSource>
<x:Array Type="{x:Type System:String}">
<System:String>あああ</System:String>
<System:String>いいい</System:String>
<System:String>ううう</System:String>
</x:Array>
</DataGridComboBoxColumn.ItemsSource>
</DataGridComboBoxColumn>
<DataGridCheckBoxColumn Binding="{Binding Check}" />
</DataGrid.Columns>
</DataGrid>
上記をテストするプログラムはたとえばこんな。
Class MainWindow
Public Property DataGridItems As New ObjectModel.ObservableCollection(Of DataGridItem)
Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
Me.DataContext = Me
DataGridItems.Add(New DataGridItem)
DataGridItems.Add(New DataGridItem)
End Sub
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
For Each x In Me.DataGridItems
Debug.Print(String.Format("{0} {1}", x.Choice, x.Check))
Next
End Sub
End Class
Public Class DataGridItem
Public Property Choice As String
Public Property Check As Boolean
End Class
あと、System.String を使用するために、clr-namespace:System;assembly=mscorlib を import しておきます。
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:System="clr-namespace:System;assembly=mscorlib"
Title="MainWindow"
Height="350"
Width="525">
posted in Program, VB.NET, WPF, xaml by ooltcloud | No Comments
2013年12月11日
VB には BASIC の時代から連綿と語り継がれている命令がありまして、End 命令もその一つ。しかしこの End 命令を安易に使うとひどい目にあう場合があります。
たとえば最近の言語では例外機構が装備されていて、Finally ブロックは必ず実行すると信じられています。しかし、End 命令を使用すると Finally ブロックは実行されません。
Module Module1
Sub Main()
Try
Console.WriteLine("終了")
End
Finally
Console.WriteLine("ここは通らない")
End Try
End Sub
End Module
End 命令は .net 的には Environment.Exit(0) で、C言語でいう exit(0); と等価です。プログラムがその場で中断されてしまいます。なのでパッと見た目正常にプロセスが落ちたように見えますが、いろいろな処理が抜け落ちてしまっている可能性があります。
特に「Finally で後処理をしているから大丈夫」という前提を持つとき、誰かが End を使用すると、その前提が覆ってしまいます。つまり、Finally への信頼が裏切られてしまいます。
また同様に、GUI 系では、プロセス(?)の終了イベントとして、MyApplication_Shutdown (WinForms) や Application_Exit (WPF) が用意されていますが、End を使用するとこのイベントが発生しません。この点も注意すべきポイントです。
したがって、End 命令は安易に使うべきではありません。特に、プロセスが終了しないから End で終了させよう、というアプローチを行うと、後日死ぬ目を見ることがあるので注意です。
ちなみに以下は End (Environment.Exit) を実行したときに通る箇所と通らない個所のまとめ。
Finalizer は実行されますが、Dispose メソッドや Finally ブロックは実行されず、Thread も唐突に閉じられます。
Module Module1
Sub Main()
' Newのみ
Dim obj = New Class1
' ワーカースレッド起動
Dim t = New System.Threading.Thread(AddressOf worker)
t.Start()
Try
System.Threading.Thread.Sleep(1000)
Console.WriteLine("終了")
Environment.Exit(0) ' End
Finally
Console.WriteLine("ここは通らない")
End Try
End Sub
' ワーカースレッド
Sub worker()
Try
Console.WriteLine("スレッド実行中")
' 無限待ち
System.Threading.Thread.Sleep(-1)
Finally
Console.WriteLine("ここは通らない")
End Try
End Sub
End Module
Class Class1
Implements IDisposable
' ファイナライザー
Protected Overrides Sub Finalize()
Console.WriteLine("ここは通る")
End Sub
#Region "IDisposable Support"
' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
Console.WriteLine("ここは通らない")
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
posted in Program, VB.NET by ooltcloud | 1 Comment
2013年12月9日
「三菱、個人向け液晶ディスプレイ事業を終息」らしい。
http://pc.watch.impress.co.jp/docs/news/20131205_626483.html
ダイアモンドトロンは、自分自身 Nanao の 54T で使っていたし、友人にも勧めたりしてました。ちょっと感慨深いものがありますね。もっとも CRT の生産ははるか昔に終わっているわけではありますが。
PC Watchの記事で振り返る三菱電機のディスプレイ
http://pc.watch.impress.co.jp/docs/topic/feature/0131207_626649.html
posted in 時事 by ooltcloud | No Comments
2013年12月9日
Windows 7 以降ではタスクバーアイコンにプログレス表示ができるようになりましたが、その実装例。
XAML 側。ProgressState を Normal にすることで表示されるようになります。
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="350"
Width="525">
<Window.TaskbarItemInfo>
<TaskbarItemInfo x:Name="TaskBarItemInfo1"
ProgressState="Normal"/>
</Window.TaskbarItemInfo>
</Window>
コードビハインド側。特に DoEvents 的な何かを入れなくても更新される模様。
For i = 0.1 To 1.0 Step 0.1
Me.TaskBarItemInfo1.ProgressValue = i
System.Threading.Thread.Sleep(1000)
Next
posted in Program, VB.NET, WPF by ooltcloud | No Comments
2013年12月9日
右クリックするとその場所に表示されるポップアップメニューが欲しい場合、ContextMenu を実装することで実現できます。
実装例は以下。
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ContextMenu x:Key="Menu1" FontSize="32">
<MenuItem Header="MenuItem1"
Click="MenuItem1_Click" />
<MenuItem Header="MenuItem2">
<MenuItem Header="MenuItem21"
Click="MenuItem21_Click" />
<MenuItem Header="MenuItem22"
Click="MenuItem22_Click" />
</MenuItem>
</ContextMenu>
</Window.Resources>
<StackPanel>
<Button Content="A"
ContextMenu="{StaticResource Menu1}" />
<Button Content="B"
ContextMenu="{StaticResource Menu1}" />
<Button Content="C"
ContextMenu="{StaticResource Menu1}" />
</StackPanel>
</Window>
上記は、複数のコントロールで同じメニューを使う、というのを前提にしたので、ContextMenu の定義は Resources に定義しています。
フォントやフォントサイズも変えられるようです。
また、上記の定義で右クリックすると ContextMenu が表示されますが、プログラムによってメニューを表示したいという場合は、たとえば以下のコードで実現できます。(ContextMenu の IsOpen を True にする)
' ボタンの ContextMenu を経由して表示
Private Sub ButtonA_Click(sender As Object, e As RoutedEventArgs)
Dim b = DirectCast(sender, Button)
b.ContextMenu.IsOpen = True
End Sub
' 直接 Resources を参照して表示
Private Sub ButtonB_Click(sender As Object, e As RoutedEventArgs)
Dim c = DirectCast(Me.Resources("Menu1"), ContextMenu)
c.IsOpen = True
End Sub
posted in Program, VB.NET, WPF by ooltcloud | No Comments
2013年12月8日
マウスをクリックした箇所の座標を取得する場合、以下のように記述すると、クリックした位置を取得することができます。
(以下は右クリックを押した時の例)
Private Sub Window1_MouseRightButtonDown(sender As Object, e As MouseButtonEventArgs) _
Handles Me.MouseRightButtonDown
Dim clientPoint = e.GetPosition(Me)
Dim screenPoint = Me.PointToScreen(clientPoint)
Debug.WriteLine("Client領域の座標(相対座標) {0}", clientPoint)
Debug.WriteLine("Screen領域の座標(絶対座標) {0}", screenPoint)
End Sub
posted in Program, VB.NET, WPF by ooltcloud | No Comments
2013年12月7日
StackPanel で積んでいって、最後のコントロールに残っている領域すべてを割り当てたい場合、たとえば以下のように実装します。
この例では、StackPanel だけでは無理そうなので DockPanel の力を借りています。
<DockPanel>
<!-- StackPanelの部分 -->
<StackPanel DockPanel.Dock="Top">
<Button Content="AAAA" />
<Button Content="AAAA" />
<Button Content="AAAA" />
<Button Content="AAAA" />
</StackPanel>
<!-- あまりの部分 -->
<TextBox AcceptsReturn="True"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"/>
</DockPanel>
2013-12-8 追記
「Grid ではダメなのか?」という指摘を受けたので Grid を使った例について記す。
ポイントは、StackPanel 部分の RowDefinition を "Auto" に設定し、あまり側の RowDefinition を "*" で設定してる点。
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- StackPanelの部分 -->
<StackPanel>
<Button Content="AAAA" />
<Button Content="AAAA" />
<Button Content="AAAA" />
<Button Content="AAAA" />
</StackPanel>
<!-- あまりの部分 -->
<TextBox Grid.Row="1"
AcceptsReturn="True"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"/>
</Grid>
posted in Program, WPF, xaml by ooltcloud | No Comments
2013年12月7日
業務アプリにありがちな、シングルウインドウで画面展開していき、子画面を閉じると親画面が表示される系の実装例。いわゆるパンくずリスト。(まあ以下の実装はリスト表示ではないので、正確にはパンくずリストではないですが)
具体的には、次の画面を .show した後に、次の画面の .Owner に親画面のインスタンスを突っ込んでおきます。
その後、親画面は .Hide で非表示にします。
子画面が閉じられたときは、.Owner を .show してやれば親画面の表示が戻ります。
.Owner の Nothing を確認しているのは、ルートウインドウは親要素がセットされていないため。
Class MainWindow
Private Shared _count As Integer = 0
Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
_count += 1
Me.Title = CStr(_count) ' いつ作った Window なのかを確認するための、デバッグ情報。
End Sub
' 子画面を開く
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
Dim f = New MainWindow
f.Show()
f.Owner = Me
Me.Hide()
End Sub
' 画面を閉じる
Private Sub MainWindow_Closed(sender As Object, e As EventArgs) Handles Me.Closed
If (Me.Owner Is Nothing) = False Then ' ルートウインドウではないなら
Me.Owner.Show()
End If
End Sub
End Class
上記はテストプログラムなので、Title に生成した Windows 番号(_count) を表示して、いつ作成したかわかるようにしています。
また、本来は複数のウインドウで呼び合いますが、枚数作るのは面倒だったので、再帰でサンプルを作っています。
posted in Program, VB.NET, WPF by ooltcloud | No Comments
2013年12月4日
Enum の要素数、あるいは最大値が欲しい場合、以下のように書きます。
また、要素数のほうはそのまま .Length メソッドで取得できますが、最大値のほうは Cast してやらないと .Max メソッドが使えません。
' 要素数を得る
Dim a = [Enum].GetValues(GetType(十干))
Console.WriteLine("要素数 = {0}", a.Length)
' 最大値を得る
Dim b = CType(a, Integer())
Console.WriteLine("最大値 = {0}", b.Max)
対象の Enum
Enum 十干
甲 = 0
乙
丙
丁
戊
己
庚
辛
壬
癸
End Enum
実行結果
要素数 = 10
最大値 = 9
続行するには何かキーを押してください . . .
posted in Program, VB.NET by ooltcloud | No Comments
2013年12月4日
Shared (Static) なメンバー変数の初期化を、各メンバー変数の初期化子で行うのではなく、まとめてどこかで…という場合には、静的コンストラクタに書けばよいらしいです。
たとえば以下のように書きます。
ポイントは Shared Sub New() に処理を書くことと、Public などのスコープは指定しないことです。
Class Class1
Public Shared Member1 As Integer
Shared Sub New()
Member1 = 100
End Sub
End Class
呼び出し側は以下。
Module Module1
Sub Main()
Console.WriteLine("{0}", Class1.Member1)
End Sub
End Module
結果。ちゃんとコンストラクタで定義した値が取得できます。
100
続行するには何かキーを押してください . . .
ちなみに、初期化子にも値を設定していました…というケースは New 側が優先されます。(普通のインスタンスの場合と同じ)
posted in Program, VB.NET by ooltcloud | No Comments
2013年12月1日
.net Framework 4 からなのか、ExpandoObject という、動的にメンバーが追加できる型ができたようです。
Dim person As Object = New Dynamic.ExpandoObject
person.ID = 1
person.Name = "Name"
Console.WriteLine(person.ID)
Console.WriteLine(person.Name)
Console.WriteLine("-----------")
Console.WriteLine(TypeName(person))
Console.WriteLine(TypeName(person.ID))
Console.WriteLine(TypeName(person.Name))
結果
1
Name
-----------
ExpandoObject
Integer
String
続行するには何かキーを押してください . . .
存在しないメンバーに代入すれば、宣言なしでメンバーができるってのは楽ですね。
ただし、これを扱うには、Option Strict は Off にしておく必要があるのと、型推論は効かさないようにする必要があります。
(Dim Dim person = New Dynamic.ExpandoObject、ではなく、Dim person As Object = New Dynamic.ExpandoObject、のように「As Object」を省略しないようにします)
posted in Program, VB.NET by ooltcloud | No Comments
2013年12月1日
以下のようなクラスがあったとして。
' 親クラス
Public MustInherit Class SuperClass
Private _superClassField As Integer = 1
Private Function superClassMethod(arg As String) As String
Return "Super " & arg
End Function
End Class
' 子クラス
Public Class SubClass
Inherits SuperClass
Private _subClassField As Integer = 2
Private Function subClassMethod(arg As String) As String
Return "Sub " & arg
End Function
End Class
このサブクラス側の Private メンバーにアクセスするには以下のようにします。
具体的には、ターゲットのクラスを GetType し InvokeMember でアクセスします。
Dim target = New SubClass
Dim t = GetType(SubClass)
Dim value1 = t.InvokeMember("_subClassField",
Reflection.BindingFlags.GetField Or
Reflection.BindingFlags.Instance Or
Reflection.BindingFlags.NonPublic,
Nothing,
target,
Nothing)
Console.WriteLine(value1)
Dim value2 = t.InvokeMember("subClassMethod",
Reflection.BindingFlags.InvokeMethod Or
Reflection.BindingFlags.Instance Or
Reflection.BindingFlags.NonPublic,
Nothing,
target,
{"Args"})
Console.WriteLine(value2)
結果
2
Sub Args
続行するには何かキーを押してください . . .
継承元の Private メンバーにアクセスしたい場合は、GetType するクラスを、アクセスしたいメンバーがいるクラス名にします。
今回の例だと、親クラスを指定して GetType します。
Dim target = New SubClass
Dim t = GetType(SuperClass)
Dim value1 = t.InvokeMember("_superClassField",
Reflection.BindingFlags.GetField Or
Reflection.BindingFlags.Instance Or
Reflection.BindingFlags.NonPublic,
Nothing,
target,
Nothing)
Console.WriteLine(value1)
Dim value2 = t.InvokeMember("superClassMethod",
Reflection.BindingFlags.InvokeMethod Or
Reflection.BindingFlags.Instance Or
Reflection.BindingFlags.NonPublic,
Nothing,
target,
{"Args"})
Console.WriteLine(value2)
結果
1
Super Args
続行するには何かキーを押してください . . .
posted in Program, VB.NET by ooltcloud | No Comments
2013年11月30日
WPF の TextBox をマウスでクリックして選択した場合、クリックした箇所に近い文字間にキャレットが挿入されます。
そうじゃなくて、IE の URL を入力するところのように、テキストを全選択したい…というケースの実装方法について。
具体的には、以下のような流れで処理しています。
- 左マウスボタンを押したとき、まだフォーカスを持っていなければ、フォーカスを強制的に得る。
- そして、イベントチェーンを切断する。(e.Handled = True)
- フォーカスイベントで、テキストを全選択する。
コードビハインド側
Class MainWindow
Private Sub TextBox_PreviewMouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs)
Dim t = CType(sender, TextBox)
If (t.IsFocused = False) Then
t.Focus()
e.Handled = True
End If
End Sub
Private Sub TextBox_GotFocus(sender As Object, e As RoutedEventArgs)
Dim t = CType(sender, TextBox)
t.SelectAll()
End Sub
End Class
XAML側
<Window ....
<Window.Resources>
<Style TargetType="TextBox">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="TextBox_PreviewMouseLeftButtonDown"/>
<EventSetter Event="GotFocus" Handler="TextBox_GotFocus"/>
</Style>
</Window.Resources>
<StackPanel>
<TextBox Text="AAAA"/>
<TextBox Text="BBBB"/>
<TextBox Text="CCCC"/>
<TextBox Text="DDDD"/>
</StackPanel>
</Window>
なんでこんな処理になるかというと、デフォルトでは、以下の動きをしているようです。(予想/根拠なし)
- 左クリックする。
- テキストボックスにフォーカスが与えられる。そして、フォーカスが与えられた段階ではキャレットはテキストの先頭にいる。
- その後、クリックした近辺にキャレットを移動する。(=MouseLeftButtonDownイベントのタイミング?)
つまり、2. のフォーカスを取得した段階でテキストを全選択 (.SelectAll) しても、その後の 3. の処理で全選択が解除(=キャレットが設定)されてしまいます。
このため、PreviewMouseLeftButtonDown イベントの段階でイベントチェーンを断ち切ることで、MouseLeftButtonDown イベントを抑止し、キャレットが移動することを阻止しています。
阻止するのはそのテキストボックスが初めてフォーカスを得るとき(クリックしたときにフォーカスがない場合)のみです。でないと、マウスクリックでキャレットを移動させることそのものができなくなってしまいます。
また、以後のイベントを抑止してしまうと、既定の TextBox に Focus を与える処理に届かなくなるので、イベントの抑止と同時にフォーカスを強制的に得るようにします。
なお、PreviewMouseLeftButtonDown イベント(トンネル イベント)と MouseLeftButtonDown イベント(バブルイベント)の違いについては以下が詳しいです。
http://msdn.microsoft.com/ja-jp/library/ms742806.aspx#how_event_processing_works
参考) イベントの伝播

posted in Program, VB.NET, WPF by ooltcloud | No Comments
2013年11月30日
Windows Forms だと Me.ControlBox = False 一発で消せるコントロールボックスですが、WPF だとそのようなプロパティは用意されておらず、結局のところ Win32API に頼る以外に方法がない模様です。
ということで、その方法を列挙。
- タイトルバー右側のコントロールボックス(最大化/最小化/閉じるボタン)と、タイトルバー左側のシステムメニューボタンの消去。
Shared Sub DisableControlBox(w As Window)
Const GWL_STYLE = -16
Const WS_SYSMENU = &H80000
Dim hwnd = (New System.Windows.Interop.WindowInteropHelper(w)).Handle
Dim currentValue = GetWindowLong(hwnd, GWL_STYLE)
Dim oldValue = SetWindowLong(hwnd, GWL_STYLE, currentValue And (Not WS_SYSMENU))
End Sub
- 最大化ボタンの無効化。
Shared Sub DisableMaximizeBox(w As Window)
Const GWL_STYLE = -16
Const WS_MAXIMIZEBOX = &H10000
Dim hwnd = (New System.Windows.Interop.WindowInteropHelper(w)).Handle
Dim currentValue = GetWindowLong(hwnd, GWL_STYLE)
Dim oldValue = SetWindowLong(hwnd, GWL_STYLE, currentValue And (Not WS_MAXIMIZEBOX))
End Sub
- 最小化ボタンの無効化。
最大化無効と最小化無効の両方を実行すると、ボタンそのものが消去されます。
Me.WindowStyle = Windows.WindowStyle.ToolWindow との違いは、システムメニューアイコンが残ることと、閉じるボタンが小さくならないことでしょうか。
Shared Sub DisableMinimizeBOX(w As Window)
Const GWL_STYLE = -16
Const WS_MINIMIZEBOX = &H20000
Dim hwnd = (New System.Windows.Interop.WindowInteropHelper(w)).Handle
Dim currentValue = GetWindowLong(hwnd, GWL_STYLE)
Dim oldValue = SetWindowLong(hwnd, GWL_STYLE, currentValue And (Not WS_MINIMIZEBOX))
End Sub
- 閉じるボタンの無効化。
閉じるボタンの無効化だけ、他と違って SetWindowLong ではなく EnableMenuItem で実現。
Public Shared Sub DisableCloseBox(w As Window)
Const SC_CLOSE = &HF060
Const MF_BYCOMMAND = &H0
Const MF_GRAYED = &H1
Dim hwnd = (New System.Windows.Interop.WindowInteropHelper(w)).Handle
Dim hMenu As IntPtr = GetSystemMenu(hwnd, False)
If hMenu <> IntPtr.Zero Then
EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND Or MF_GRAYED)
End If
End Sub
あと、上記を実行するために必要な Declare 宣言は以下。
- コントロールボックスの消去、最大化/最小化ボタンを無効にするときに必要な Declare 宣言。
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (
ByVal hWnd As IntPtr,
ByVal nIndex As Integer) As Integer
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (
ByVal hWnd As IntPtr,
ByVal nIndex As Integer,
ByVal dwNewLong As Integer) As Integer
- 閉じるボタンを無効にするときに必要な Declare 宣言。
Private Declare Function GetSystemMenu Lib "user32" (
ByVal hwnd As IntPtr,
ByVal bRevert As Integer) As Long
Private Declare Function EnableMenuItem Lib "user32" (
ByVal hWnd As IntPtr,
ByVal uIDEnableItem As UInteger,
ByVal uEnable As UInteger) As Boolean
あと、注意点としては、上記の方法で閉じるボタンを無効化/消去しただけでは、ALT+F4 を押すと Window は閉じてしまいます。
このため、Window を閉じたくない場合は、Window の Closing イベントで e.Cancel = True で閉じなくするなどの対策が必要になります。
しかし WPF・・・、このかゆいところに手が届かない感じは、早めになんとかしてほしいのではありますが(汗
参考) Window の各部の名称

posted in Program, VB.NET, WPF by ooltcloud | No Comments
2013年11月26日
キーボードでのコントロールの移動は、基本は TAB 押下で移動させるのが Windows のデザインのはずですが、Enter で移動させたい(あるいはさせていた)という場合があります。
その場合は、以下の EnterThenNextFocus を作成して、これを KeyDown イベントで呼び出されるようにすることで実現できます。
コードビハインド
Class MainWindow
Private Sub EnterThenNextFocus(sender As Object, e As KeyEventArgs)
If e.Key = Key.Enter Then
Dim u = DirectCast(sender, UIElement)
u.MoveFocus(New TraversalRequest(FocusNavigationDirection.Next))
End If
End Sub
End Class
XAML
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="TextBox">
<EventSetter Event="KeyDown" Handler="EnterThenNextFocus"/>
</Style>
<Style TargetType="ComboBox">
<EventSetter Event="KeyDown" Handler="EnterThenNextFocus"/>
</Style>
</Window.Resources>
<StackPanel>
<TextBox TabIndex="1"/>
<TextBox TabIndex="4"/>
<ComboBox TabIndex="2"/>
<TextBox TabIndex="3"/>
</StackPanel>
</Window>
posted in Program, VB.NET, WPF, xaml by ooltcloud | No Comments
2013年11月25日
テスト用のモックを作りたい時など、メソッドの内容をテスト用のものに差し替えたい場合があります。
これを実現するために RealProxy を使用する方法があります。
大前提として、以下の Import を追加しておきます。
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Proxies
Imports System.Runtime.Remoting.Messaging
まずターゲットとなるクラスを作成します。
普段と異なるのは、MarshalByRefObject を継承しておく点です。
Public Class Class1
Inherits MarshalByRefObject
Public Function Read() As String
Return "本物"
End Function
End Class
次に以下のプロキシークラスを作ります。
ReturnMessage クラスが、メソッドの戻り値を作る部分です。
今回は「偽物」を Return として戻す設定です。
Public Class Class1Proxy
Inherits RealProxy
Public Sub New()
MyBase.New(GetType(Class1))
End Sub
Public Overrides Function Invoke(msg As IMessage) As IMessage
Dim mm = CType(msg, IMethodMessage)
Return New ReturnMessage("偽物!", Nothing, 0, mm.LogicalCallContext, mm)
End Function
End Class
これを以下の手順で呼びます。
Module Module1
Sub Main()
' プロキシーを生成する
Dim proxy = New Class1Proxy
Dim p = proxy.GetTransparentProxy
' 作成されたプロキシーを、元のクラスにキャストする
Dim a = CType(p, Class1)
' 呼んでみる
Console.WriteLine("{0}", a.Read)
End Sub
End Module
しかしこのコードだと、呼ばれたメソッドが何であれ、必ず "偽物!" が戻ってしまいます。
何のメソッドが呼ばれたかを確認するためには、前述 Class1Proxy.Invoke の mm.MethodBase.Name を使用することで可能です。
本物のメソッドを呼びたい、という場合は、RemotingServices.ExecuteMessage を使用します。
以上を踏まえると、Class1 のうち Read() のみを模擬で、他は本物のメソッド呼びたい場合、Class1Proxy は以下のように書けます。
Public Class Class1Proxy
Inherits RealProxy
Private _target As Class1
Public Sub New(target As Class1)
MyBase.New(GetType(Class1))
' 本物を呼び出す用のインスタンスを外部から受ける
_target = target
End Sub
Public Overrides Function Invoke(msg As IMessage) As IMessage
Dim mm = CType(msg, IMethodMessage)
' メソッド名で分岐
Select Case mm.MethodBase.Name
Case "Read"
' 模擬で戻す
Return New ReturnMessage("偽物!", Nothing, 0, mm.LogicalCallContext, mm)
Case Else
' 本物を実行
Return RemotingServices.ExecuteMessage(_target, mm)
End Select
End Function
End Class
で、これでテスト用のモックが作れるかいうと… ちょっと面倒な気がします。
理由は以下。
- Proxy クラス (上述では Class1Proxy) が難解。
- 実コードで使っている Class1 インスタンスを Class1Proxy インスタンスに差し替える必要がある。
- Public や Private ならなんとか差し替えられるが、ローカルスコープで使われている場合は手が出ない。
- ターゲットとなるクラスは MarshalByRefObject を継承する必要がある。
個人的には 4. が鬼門。テストのためにリリースコードを汚す、というのがどうも好きになれないので。
リリースコードを汚す前提なら、テスト用の Interface を切ったほうがスマートかな、という気がしていたりします。
posted in Program, VB.NET by ooltcloud | No Comments
2013年11月25日
たとえばこんなクラスがあったとして。
' 親クラス
Public MustInherit Class SuperClass
Private Function SuperClassMethod() As String
Return "Super"
End Function
End Class
' 子クラス
Public Class SubClass
Inherits SuperClass
Private Function SubClassMethod() As String
Return "Sub"
End Function
End Class
継承元クラスの Private を呼び出す場合、テストはこう書けます。
Imports Microsoft.VisualStudio.TestTools.UnitTesting
<TestMethod()> Public Sub UnitTest2()
Dim target = New ClassLibrary1.SubClass
' 子クラス側アクセス
Dim po = New PrivateObject(target)
Dim retSub = po.Invoke("SubClassMethod")
Assert.AreEqual(retSub, "Sub")
' 親クラス側アクセス
Dim poSuper = New PrivateObject(target, New PrivateType(GetType(ClassLibrary1.SuperClass)))
Dim retSuper = poSuper.Invoke("SuperClassMethod")
Assert.AreEqual(retSuper, "Super")
End Sub
ポイントは、親クラスのメソッドを呼びたい場合は、PrivateObject のコンストラクタ第二引数に、親クラスの型を指定した PrivateType のインスタンスを渡すところです。
また、このインスタンス (poSuper) では、子クラス側のメソッドは呼べません。したがって子クラスのメソッドを呼びたい場合は、子クラスアクセス用のインスタンスを別に作る必要があります。
posted in Program, VB.NET by ooltcloud | No Comments
2013年11月21日
VC++(VS2012) で以下のプログラムを、コマンドラインでコンパイルして実行。
#include <stdio.h>
void func() {
int a[10];
int i;
printf("-----------");
for (i=0; i<10; i++) {
printf("%08xn",a[i]); // 初期化前の値を表示
a[i] = 0x1234; // 初期化?
}
}
int main() {
func(); // 一回目
func(); // 二回目
}
コンパイルのコマンドはこう。
cl ConsoleApplication1.c
結果はこんな。自動変数は初期化されていないのがわかる。
C>test
-----------
011937fb
00e0f708
01199118
00e0f784
011924a0
35abafe8
fffffffe
0119538c
01195457
011937fb
-----------
00001234
00001234
00001234
00001234
00001234
00001234
00001234
00001234
00001234
00001234
次に、VS2012 の IDE 上で、「Win32 コンソールアプリケーション」で作成、コンパイルしてみる。ソースコードは以下。
#include "stdafx.h"
void func() {
printf("-----------n");
int a[10];
for (int i=0; i<10; i++) {
printf("%08xn",a[i]); // 初期化前の値を表示
a[i] = 0x1234; // 初期化?
}
}
int _tmain(int argc, _TCHAR* argv[])
{
func(); // 一回目
func(); // 二回目
return 0;
}
結果はこんな。
-----------
cccccccc
cccccccc
cccccccc
cccccccc
cccccccc
cccccccc
cccccccc
cccccccc
cccccccc
cccccccc
-----------
cccccccc
cccccccc
cccccccc
cccccccc
cccccccc
cccccccc
cccccccc
cccccccc
cccccccc
cccccccc
0xcc で初期化されている。(*1)
おまけに C# でもやってみる。
using System;
namespace ConsoleApplication1
{
class Program
{
static void func()
{
Console.WriteLine("-----------");
int[] a = new int[10];
for (int i = 0; i < 10; i++)
{
Console.WriteLine("{0}", a[i]);
a[i] = 0x1234;
}
}
static void Main(string[] args)
{
func(); // 一回目
func(); // 二回目
}
}
}
結果はこう。
-----------
0
0
0
0
0
0
0
0
0
0
-----------
0
0
0
0
0
0
0
0
0
0
C# はつまらん…(何
(*1)
これは、デバックモードで実行した結果です。
デバックモードでは、コンパイルオプション /RTCs 相当が指定されていることに起因します。
http://msdn.microsoft.com/ja-jp/library/8wtf2dfz.aspx
したがって、このオプションを外せば、C++ の場合でも上記 C言語と同様に自動変数は初期化されません。
posted in Program, Visual C++ by ooltcloud | No Comments
2013年11月19日
Enumerable.Repeat は 第一引数で得た値を、第二引数の指定数、繰り返し代入します。
気を付けなくてはならないのは、第一引数の処理の実行は1回だけという点です。第一引数の処理が、第二引数の指定数だけ実行されるわけではない点です。
したがって、第一引数が戻す型が参照型の場合、ひどい目にあう場合があります。
コード
Module Module1
Sub Main()
Dim a() = Enumerable.Repeat(New Class1, 10).ToArray
Console.WriteLine(String.Join("-", From x In a Select x.Value))
a(0).Value = 1 ' 要素のうち1つしか変更していない(つもり)
Console.WriteLine(String.Join("-", From x In a Select x.Value))
End Sub
End Module
Class Class1
Sub New()
Console.WriteLine("New!")
End Sub
Public Value As Integer
End Class
結果
New! ← "New!" は一回しか表示されない
0-0-0-0-0-0-0-0-0-0
1-1-1-1-1-1-1-1-1-1 ← 全要素が"1"に変更されたかのように見える
続行するには何かキーを押してください . . .
posted in Program, VB.NET by ooltcloud | No Comments
2013年11月17日
たとえば、テスト対象となる、こんなメソッドがあった場合。(ルート名前空間は "ClassLibrary1" であるとします)
Public Class Class1
Private Function func1(source As Integer(), index As Integer) As Integer
Return source(index)
End Function
End Class
テストはこう書けます。
Imports Microsoft.VisualStudio.TestTools.UnitTesting
<TestClass()> Public Class UnitTest1
<TestMethod()> Public Sub TestMethod1()
Dim source = New Integer() {100, 200, 300}
Dim target = New ClassLibrary1.Class1
Dim po As New PrivateObject(target)
Dim result = po.Invoke("func1", {source, 2})
Assert.AreEqual(result, 300, "テスト")
End Sub
End Class
Microsoft.VisualStudio.TestTools.UnitTesting 名前空間に、PrivateObject というクラスがあるようなので、それを使うと呼び出せるようです。
リフレクションのラッパー的な感じなので、メソッド名を文字列で渡す必要がある(=インテリセンスは効かない)のがいまひとつなところですが、リフレクションを生で呼び出すよりは、はるかに楽に書けます。
posted in Program, VB.NET by ooltcloud | No Comments
2013年11月11日
WindowsRT 端末(ASUS TF-600T) でキーボードを装着した時、タッチパッドが使えるようになりますが、同時にタッチパッドへのタッピング操作も可能になってしまいます。
これを抑止(=タッピング禁止)したい場合、以下でとりあえずは抑止できるようです。
キー
HKEY_LOCAL_MACHINESOFTWARESynapticsSynTPDefaults
値の名前
Gestures
値のデータ
3 → 2 にする。

posted in Windows, 環境設定 by ooltcloud | No Comments
2013年11月11日
Grid にオブジェクトを置いたとき、Grid 領域外にある図形が欠けることがあります。
もちろん、Grid の外にはみ出た領域もそうですが、分割した領域からはみ出ても欠けます。
たとえば、以下のような xaml を記述した場合。
# Ellipse オブジェクトは、中央の領域(Grid.Column="1" Grid.Row="1")に置いています。
<Grid Width="300" Height="300">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Ellipse Grid.ColumnSpan="1" Grid.RowSpan="1"
Grid.Column="1" Grid.Row="1"
Height="300" Width="300"
Margin="-100,-100,0,0"
Fill="Red"/>
</Grid>
すると、こんな感じに表示されます。
上辺/左辺は領域を超えても表示されますが、下辺/右辺を超えた部分は非表示になります。(クリッピングされる。)

それでは、上辺/左辺は領域を超えても必ず表示されるのか?、というと、それはそうでもないようで。
たとえば、以下のような xaml を記述した場合。
# Path オブジェクトは、中央右下の領域(Grid.Column="2" Grid.Row="2")に置いています。
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Path Grid.Column="2" Grid.Row="2"
Data="M0,0 m0,-50 l50,86.6 -100,0 z" Stroke="Red" Fill="Red"/>
</Grid>
Path の図形そのものがマイナスの座標を持っているせいなのか

上辺/左辺を超えても、表示され続けますが…

一度、右辺、下辺の境界を図形が超えると、境界外が一気に消去されます。(上辺/左辺側も含めて)

要するにオブジェクトが境界外にはみ出る場合は要注意ということで(汗
対策的には、下辺/右辺側が領域外になるからまずいわけだから、Grid.RowSpan とかで領域を広げてやれば、とりあえずは回避できます。
posted in Program, WPF, xaml by ooltcloud | No Comments
2013年11月10日
WPF アプリケーションの場合、Application.DoEvents() が標準では呼び出せない(*1)ので別の方法を検討する必要があります。
具体的には、DoEvents したい箇所で、.Dispatcher.Invoke を DispatcherPriority.Render を指定して、空の処理を呼ぶだけでよいです。
Imports System.Windows.Threading
Imports System.ComponentModel
Class MainWindow
Implements ComponentModel.INotifyPropertyChanged
Public Property A As String ' ← これを xaml 側で Binding する
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
For i = 1 To 10
' 更新処理
A = Now.ToString
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(""))
' DoEvents
Me.Dispatcher.Invoke(DispatcherPriority.Render, Sub()
' 処理はなし
End Sub)
System.Threading.Thread.Sleep(1000)
Next
End Sub
Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
Me.DataContext = Me
End Sub
DoEvents よりもコード量が多いのでいまひとつな感じもありますが、DoEvents だとボタンクリックとかの処理が割り込んで疑似マルチスレッド状態になることを考えると、この方法は結構妥当な気がしています。
(*1)
System.Windows.Forms を参照設定し、System.Windows.Forms.Application.DoEvents() を呼べばいける、という話もないわけではない…
posted in Program, WPF, xaml by ooltcloud | No Comments
2013年11月10日
Linq で 列のデータを平均を求めた例。
以下のコードの場合、左側一列目 10,20,51 の平均(=27)を計算し、それを列分繰り返す。
Sub Main()
Dim table()() = {New Double() {10, 20, 30, 40},
New Double() {20, 40, 62, 74},
New Double() {51, 45, 25, 30}}
Dim columnAverage =
From column
In Enumerable.Range(0, table(0).Length)
Select
(
From row
In Enumerable.Range(0, table.Length)
Select table(row)(column)
).Average
For Each n In columnAverage
Console.WriteLine(n.ToString)
Next
End Sub
結果
27
35
39
48
SQL の相関サブクエリーのような感じに…(汗
Enumerable.Range 使ったりとか、table(0).Length 使ったりとか、なんかいまいちな気もしますが、とりあえずは集計できるということで…
.Average を別のメソッド(.Sumとか)に変えれば他の集計もできたりとか。
posted in Program, VB.NET by ooltcloud | No Comments
2013年10月17日
Excel VBA のコードをテキストに吐き出したりしたい場合があります。(バージョン管理に突っ込みたいときとか)
しかし毎度手で Export するのは面倒なので VBA にやらせたい場合、たとえば以下のように書くと Export できます。
Sub CodeExport()
' 任意の WorkBook を指定 (ActiveWorkBook なり Workbooks.Open なり…)
Dim w As Workbook
Set w = ThisWorkbook
' Export
Call w.VBProject.VBComponents("Module1").Export("C:Module1.bas")
End Sub
上記はファイル名を個別指定の例ですが、Book内のモジュールを一気に Export したい場合は、VBComponents を for each で回して Name で名前が取れるのであとは良しなに…
Sub CodeList()
' 任意の WorkBook を指定 (ActiveWorkBook なり Workbooks.Open なり…)
Dim w As Workbook
Set w = ThisWorkbook
' 列挙
For Each x In w.VBProject.VBComponents
Debug.Print x.Name
Next
End Sub
逆に import したい場合は以下のようにします。
import の場合、同名のモジュールがあると自動的にリネームされるので、先に削除してから import を行います。
Sub CodeReplace()
' 任意の WorkBook を指定 (ActiveWorkBook なり Workbooks.Open なり…)
Dim w As Workbook
Set w = ThisWorkbook
' 一旦削除
Call w.VBProject.VBComponents.Remove( _
w.VBProject.VBComponents("Module1"))
' その後 Import
Call w.VBProject.VBComponents.Import("C:Module1.bas")
End Sub
ただ、この方法は欠点があります。
Sheet や Workbook のマクロはクラスモジュールとして import されます。そのため、本来(Sheet や Workbook のマクロ)の位置 に直接 import できません。
これは Excel の仕様のようです。(手動での import でもそういう動作になります)
また、上記のコードを動かすためには、セキュリティの設定を変更する必要があります。
「ファイル」→「オプション」→「セキュリティ」→「セキュリティセンターの設定」とたどって、「VBA プロジェクト オブジェクト モデル へのアクセスを信頼する」にチェックを入れておきます。

posted in Excel, Office by ooltcloud | No Comments
2013年10月10日
Application.Resources などの親側の Resource で x:key なしの TargetType 指定したスタイルを、Window.Resources などの子側で継承したい場合のやり方。
その TargetType の型をそのまま継承すればよいようです。
<Window.Resources>
<Style TargetType="DataGrid" BasedOn="{StaticResource {x:Type DataGrid}}">
<Setter Property="IsReadOnly" Value="True"/>
</Style>
</Window.Resources>
たとえば、以下のような xaml を記述します。
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="200" Width="200">
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="LightGreen"/>
</Style>
</Window.Resources>
<StackPanel>
<Grid>
<!-- 親要素(Window.Resources) の Style が反映される -->
<Button Content="Button"/>
</Grid>
<Grid>
<Grid.Resources>
<!-- BasedOn がないと Window.Resources での設定が反映されない -->
<Style TargetType="Button">
<Setter Property="Foreground" Value="White"/>
</Style>
</Grid.Resources>
<Button Content="Button"/>
</Grid>
<Grid>
<Grid.Resources>
<!-- BasedOn を付加すると親要素(Window.Resources) の Style が反映される -->
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Foreground" Value="White"/>
</Style>
</Grid.Resources>
<Button Content="Button"/>
</Grid>
</StackPanel>
</Window>
すると表示は以下のようになります。

一番上の Button は Window.Resources の Style の通り背景色が緑で表示されます。
しかし、その下の Button は Grid.Resources で文字色を設定したために、背景色がデフォル(灰色)に戻ってしまっています。
一番下の Button は、BasedOn により親の Style を継承しているので、背景色は緑のまま、文字色を白にすることができています。
posted in Program, xaml by ooltcloud | No Comments
2013年10月10日
VB.NETで空配列の生成したいときの記法。
' 一次元配列の例
Public Property s1 As String() = New String(10) {}
' 二次元配列の例
Public Property s2 As String(,) = New String(10, 15) {}
http://ooltcloud.sakura.ne.jp/blog/200910/article_02012300.html との違いは、型を指定してみたところ。
ローカル変数ではない場合、型推論が効かなくて、型指定がない場合には Object 型として評価されるようなので。
posted in Program, VB.NET by ooltcloud | No Comments
2013年10月9日
ASLR(Address Space Layout Randomization) の実験をしてみた。
- こんなコードを書く。
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
char a;
printf("%xn",(int)&a);
return 0;
}
- デフォルトのままでコンパイル/実行すると、実行結果が実行の度に毎回変わる。
- リンカーのオプションで「ランダム化されたベースアドレス」を「はい」から「いいえ」に変えてみる。
- この設定でコンパイルして実行すると、実行結果は毎回同じになる。
なるほどね…
有効にしていれば、実行のたびにアドレスが変わるから、バッファーオーバーフローがあっても任意のコードへのジャンプが難しくなるわけか・・・
posted in Program, Visual C++, Windows by ooltcloud | No Comments
2013年9月10日
php って XAMPP とかで頑張ってインストールしないと遊べないと思っていましたが、zip 展開してコマンドラインで実行ってできるんですね。
以下、簡単にその手順をメモ。
- php のダウンロード
ダウンロードはここから。
http://windows.php.net/download/
とりあえず、よくわかりませんが、「VC11 x86 Thread Safe」の「Zip」をダウンロードします。
- インストール
適当なフォルダに zip を展開します。
- コードを書く
で、とりあえず Hello World なコードを書きます。ファイル名は hello.php で保存。
<?php
echo "Hello world";
?>
- 実行
コマンドラインで、
php hello.php
とすると、実行できます。
posted in PHP, Program by ooltcloud | No Comments
2013年8月29日
[VB.NET] ワーカースレッドから コントロール(UI スレッド)へのアクセス その1 で、プラットホームごとで書き方が違うよ…_| ̄|○ ということでしたが、書き方を共通にする方法があります。
以下のように書くことで、すべてのプラットホーム(Windows Forms / WPF / Windows Phone / Silverlight / WinRT)共通で記述できます。
ポイントは Dispather を使わず、Task を使用し、TaskScheduler パラメータに UI スレッドの同期コンテキストを指定して実行するところです。
Class MainWindow ' この行は各プラットホーム個別
Private _syncContext = Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext
Sub worker1()
Dim t = New Threading.Tasks.Task( _
Sub()
Button1.Content = Date.Now.ToString ' Windows Forms の場合は Button1.Text
End Sub)
t.Start(_syncContext)
End Sub
ただし、上記を書くには、以下が最低限必須です。
- .NET Framework は 4 以上 #.NET Framework 2系(2.0~3.5) は不可
- Windows Phone は 8 以上 # Windows Phone 7 は不可
- Silverlight は 5 以上 # Silverlight 4 は不可
tags: ワーカースレッドから コントロール(UI スレッド)へのアクセス
posted in Program, VB.NET by ooltcloud | No Comments
2013年8月29日
たとえばワーカースレッドを作って、ワーカースレッド上で重い処理を走らせ、その結果をコントロールに表示させようとします。
Private Sub Button1_Click(...
Dim t = New Threading.Thread(AddressOf worker1)
t.Start()
End Sub
Sub worker1()
' 重い処理(略)
' 重い処理の結果を書く
Button1.Text = Now.ToString ' エラーになる
End Sub
ところが、これはエラーになります。コントロールへのアクセスは UI スレッドからしかアクセスできないためです。
System.InvalidOperationException が発生しました。
有効ではないスレッド間の操作:
コントロールが作成されたスレッド以外のスレッドからコントロール 'Button1' がアクセスされました。
これを回避するためには、ワーカースレッドから UI スレッドに処理をお願い(Invoke)する必要があります。
ところが、この UI スレッドにお願いする方法が、使用するアプリケーションプラットホームによって書き方が異なります。
以下列挙。
- Windwos Forms の場合
Me.BeginInvoke、または Me.Invoke を使用します。
Control クラスのメソッドのようなので、Button.Invoke でも可能ですが、Me(=Form)でいいと思います。
Sub worker1()
Me.BeginInvoke( _
Sub()
Button1.Text = Date.Now.ToString
End Sub)
End Sub
- WPF の場合
Application.Current.Dispatcher.BeginInvoke、または Application.Current.Dispatcher.Invoke を使用します。
Sub worker1()
Application.Current.Dispatcher.BeginInvoke( _
Sub()
Button1.Content = Date.Now.ToString
End Sub)
End Sub
- Windows Phone(Silverlight系)の場合
Deployment.Current.Dispatcher.BeginInvoke を使います。 Silverlight 系は Invoke はないみたいですね。
Sub worker1()
Deployment.Current.Dispatcher.BeginInvoke( _
Sub()
Button1.Content = Date.Now.ToString
End Sub)
End Sub
- WinRT(ストアアプリ系)の場合
Me.Dispatcher.RunAsync を使います。
"Dim dummy =" はコンパイラーの警告回避用です(汗
Sub worker1()
Dim dummy = Me.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, _
Sub()
Button1.Content = Date.Now.ToString
End Sub)
End Sub
Invoke 相当の動作にするためには、"Dim dummy =" の部分を "Await" に変えるか、次の行に "Await dummy" を追加して待たせます。
以下は "Await dummy" を追加してみた例。(Sub のところの Async も忘れずに)
Async Sub worker1()
Dim dummy = Me.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, _
Sub()
Button1.Content = Date.Now.ToString
End Sub)
Await dummy
End Sub
また、ストアアプリではワーカースレッドの生成に Threading.Thread が使えないので、Threading.Tasks.Task で生成しています。
Private Sub Button1_Click(...
Dim t = New Threading.Tasks.Task(AddressOf worker1)
t.Start()
End Sub
tags: ワーカースレッドから コントロール(UI スレッド)へのアクセス
posted in Program, VB.NET by ooltcloud | 1 Comment
2013年8月28日
Invoke と BeginInvoke の動作の違いについて軽くまとめ。
Button1 を押したあとに Button2 を押して、作成されるメッセージの違いをみます。
- Invoke の場合。
Public Class Form1
Private _message As String
Private Sub Button1_Click(...
_message = "AAA"
Me.Invoke(Sub()
_message &= "BBB"
End Sub)
_message &= "CCC"
End Sub
Private Sub Button2_Click(...
Console.WriteLine(_message)
End Sub
End Class
結果(作成されたメッセージ)
AAABBBCCC
- BeginInvoke の場合。
Public Class Form1
Private _message As String
Private Sub Button1_Click(...
_message = "AAA"
Me.BeginInvoke(Sub()
_message &= "BBB"
End Sub)
_message &= "CCC"
End Sub
Private Sub Button2_Click(...
Console.WriteLine(_message)
End Sub
End Class
結果(作成されたメッセージ)
AAACCCBBB
posted in Program, VB.NET by ooltcloud | No Comments
2013年8月25日
WPF の DataGrid のヘッダーの調整に難儀したので、まとめがてらメモ。
完成系のイメージは以下の通り。

ところが、デフォルトの設定では、以下のように表示します。

そこで、以下の設定をすることで、完成形のイメージを作りました。
<DataGrid ColumnHeaderHeight="40" Margin="10">
<!-- 列ヘッダーのみ表示する(本来はDataGridタグ内の属性に記載の事) -->
<DataGrid.HeadersVisibility>Column</DataGrid.HeadersVisibility>
<DataGrid.Columns>
<DataGridTextColumn Header="あああ" Width="3*" />
<DataGridTextColumn Header="いいい
ううう" Width="5*" />
<DataGridTextColumn Header="えええ" Width="5*"/>
</DataGrid.Columns>
<DataGrid.ColumnHeaderStyle>
<Style TargetType="DataGridColumnHeader">
<!-- ヘッダーの罫線を黒にする -->
<Setter Property="BorderThickness" Value="0,0,1,1"/>
<Setter Property="BorderBrush" Value="Black"/>
<!-- ヘッダー文字をセンタリングする -->
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="TextBlock.TextAlignment" Value="Center"/>
</Style>
</DataGrid.ColumnHeaderStyle>
<DataGrid.Items>
<!-- ここはフォーマット確認用のダミーなのでデタラメ -->
<TextBox></TextBox>
<TextBox></TextBox>
<TextBox></TextBox>
</DataGrid.Items>
</DataGrid>
以下、設定のポイントを列挙します。
- ヘッダーの罫線の色を変える
ColumnHeaderStyle の BorderBrush で色を、BorderThickness で線の太さを設定しました。
BorderThickness は四辺全部に線を引いてしまうと、線の太さが倍になって見えるので、右辺と下辺のみに線を入れました。(データ部の線の引き方とあわせた感じです)
<DataGrid.ColumnHeaderStyle>
<Style TargetType="DataGridColumnHeader">
<!-- ヘッダーの罫線を黒にする -->
<Setter Property="BorderThickness" Value="0,0,1,1"/>
<Setter Property="BorderBrush" Value="Black"/>
- センタリングする
ColumnHeaderStyle の HorizontalContentAlignment と TextBlock.TextAlignment で水平方向のセンタリングをします。片側だけ設定したのでは見た目は左寄せに見えるので、両方設定することが重要です。
VerticalContentAlignment はデフォルトが Center なので今回はケースでは必要ないです。上寄せとかにする場合はここを操作します。
<DataGrid.ColumnHeaderStyle>
<Style TargetType="DataGridColumnHeader">
<!-- ヘッダー文字をセンタリングする -->
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="TextBlock.TextAlignment" Value="Center"/>
- 行ヘッダーを消す
行ヘッダーを設定しなくても表示はされてしまうので、HeadersVisibility に Column を設定することで、列ヘッダーのみを表示するように(行ヘッダーを表示しないように)します。
(以下は要素ではなく属性に設定する場合の記述例)
<DataGrid HeadersVisibility="Column">
- 複数行テキストの設定
複数行のテキストを属性値として指定する場合は、改行コード(
)を指定します。
<DataGridTextColumn Header="いいい
ううう" />
- 列幅の比率指定
列幅(DataGridTextColumn.Width)の指定に "*"(star) が使えます。
<DataGridTextColumn Header="あああ" Width="3*" />
posted in Program, WPF, xaml by ooltcloud | No Comments
2013年8月18日
バインディング時のフォーマッティングは StringFormat を使うことで対応できる模様。
小数点の桁数を指定する場合。
<TextBlock Text="{Binding AAA,StringFormat=0.00}"/>
時刻を指定する場合。
<TextBlock Text="{Binding AAA,StringFormat=HH:mm:ss}"/>
"," がフォーマット文字列に含まれる場合は "" でエスケープしてやればよいようです。
<TextBlock Text="{Binding AAA,StringFormat=0,000.00}"/>
参考:複合書式表現
http://ooltcloud.sakura.ne.jp/blog/201005/article_03023842.html
posted in Program, xaml by ooltcloud | No Comments
2013年8月16日
ViewModel で作成したクラスを ルート要素の Panel の DataContext にデータバインドする際の手順のまとめ。
- ViewModel 用のクラスを作ります
ViewModel 用のクラスを作ります。 (以下では「MainWindowViewModel」が相当)
Class MainWindow
End Class
Class MainWindowViewModel
Public Property AAAA As Integer = 100
Public Property BBBB As String = "ABCD"
Public Property CCCC As TestClass = New TestClass With {.Age = 18, .Name = "test"}
Public Property DDDD As Double() = New Double(10) {}
End Class
Class TestClass
Public Property Name As String
Public Property Age As Integer
End Class
- ビルドします
XAML editor 側で MainWindowViewModel の内容が正しく評価されるようにするためにビルドします。
以後 ViewModel の変更を行うたびにリビルドします。
- XAMLを編集します
- xmlns:local="clr-namespace:WpfApplication1" を追記します
(「WpfApplication1」 は自アプリケーション名です。)
- Window.Resources に local:MainWindowViewModel のエントリーを追記します。
- ルートパネルの DataContext 属性に"{StaticResource ViewModel}"を追記します。
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="100" Width="200">
<Window.Resources>
<local:MainWindowViewModel x:Key="ViewModel" />
</Window.Resources>
<Grid DataContext="{StaticResource ViewModel}">
<Button Content="Button1" Margin="10" />
</Grid>
</Window>
- バインディングを指定します
上記の準備を終えると、Button等のコントロールを選択し「~のデータバインドを作成」などを選択すると、ViewModelの情報が表示されるようになります。
- 指定した後の例
上記4.のダイアログで実際に選択してみると、XAML が以下のように変更されます。
<Grid DataContext="{StaticResource ViewModel}">
<Button Content="{Binding CCCC.Name}" Margin="10" />
</Grid>
posted in Program, VB.NET, xaml by ooltcloud | No Comments
2013年8月13日
MVVM モデルで ViewModel から View を操作する場合は Messenger という仕組みを使う…らしいのですが、理解が難しかったので、自分なりにまとめなおしてみます。
結論的には、以下の 2 の内容か、頑張っても 5 の内容で勝負であって、Messenger の実装はやりすぎという感じがします。まあ私に取り回す実力がないだけかもしれませんが(汗
- まず「ViewModel から View を操作したいケース」とは何か
たとえば、WinForm とかで以下のようなコードを書きたいケースです。
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
MsgBox("Hello")
End Sub
簡単ですね。
- 上記を ViewModel から実行するとどうなるか
なにも考えなければ、以下で OK のはずです。
Class MainWindow
Private _viewModel As ViewModel = New ViewModel
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
' 操作類は、viewModel 側のメソッドで実行させたいので、転送する
_viewModel.ShowMsgBox()
End Sub
End Class
Class ViewModel
Public Sub ShowMsgBox()
MsgBox("Hello")
End Sub
End Class
- 疑問1:ViewModel から 直接 MsgBox を実行していいのか?
MVVM モデルではこれを嫌っているようです。予想される問題は以下の2つ。
- ViewModel に UI(入力操作) が含まれていることで、単体テストが難しくなること。
- MsgBox という命令自体が View そのものであること。
その他には「デザイナーとプログラマーの分業が難しい」とかありそうですが、とりあえず無視とします。
- 疑問2:そもそも View(コードビハインド) に直接 MsgBox を書いてはだめなのか?
嫌われる理由としては、View にビジネスロジック(MVVM でいう ViewModel 部分 / MVC でいう Controller 部分) が混じってしまう、という点です。
# MsgBox 自体は View ですが「MsgBox を表示する」はビジネスロジックです。
- ではどうするか?
たとえば、上記2.で書いたコードを以下のように書き換えます。
Class MainWindow
Private WithEvents _viewModel As ViewModel = New ViewModel
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
' 操作類は、viewModel 側のメソッドで実行させたいので、転送する
_viewModel.ShowMsgBox()
End Sub
Private Sub _viewModel_RequestShowMsgBox() Handles _viewModel.RequestShowMsgBox
MsgBox("Hello")
End Sub
End Class
Class ViewModel
Public Event RequestShowMsgBox()
Public Sub ShowMsgBox()
' MsgBoxの表示をお願いする。
RaiseEvent RequestShowMsgBox()
End Sub
End Class
こうすることで、ViewModel から View のコードは排除することができます。
これで View のことは View側 (コードビハインド側) に集約できます。つまり、MsgBox を デザインがリッチなダイアログに変更したいといった場合も ViewModel は変更せず、View 側の変更だけで対応可能です。
また、ViewModel はユーザー入力から切り離されているので、直接単体テストすることが可能です。
今回の例では実装されていませんが、ユーザー入力の入力内容を ViewModel に戻しているケースも、ViewModel からのイベントを受けるテストスタブを作ることで、単体テストが可能です。
- MVVM モデルにおける Messenger クラスとは
要するに、上記のような仕組みを用意するための、一連のクラス群です。
上記 5 では、イベントをコードビハインドに通知していますが、本家(?)のメッセンジャーはもうちょっと複雑です。
View 部分の処理 (今回のでは MsgBox 相当) をコマンドオブジェクトとしてラップし、それをコードビハインドではなく、直接 XAML に記載する手法のようです。
- Messenger クラスを実装した場合はどうなるか
こんな感じ。
しかし、共通部品として隠蔽/再利用できるものがあるとしても、これだけのコードを書く必要があるというのはちょっと…(汗
コード部分
Class MainWindow
Private _viewModel As ViewModel = New ViewModel
Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
Me.DataContext = _viewModel
End Sub
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
_viewModel.ShowMsgBox()
End Sub
End Class
Class ViewModel
Public Property RequestShowMsgBox As Messenger = New Messenger
Public Sub ShowMsgBox()
' MsgBoxの表示をお願いする。
Me.RequestShowMsgBox.Raise(
New Message("Hello"),
Sub(args)
MsgBox(args.Response, , "view操作後の処理")
End Sub
)
End Sub
End Class
Class ConfirmAction
' 参照設定: C:Program Files (x86)Microsoft SDKsExpressionBlend.NETFrameworkv4.5LibrariesSystem.Windows.Interactivity.dll
Inherits System.Windows.Interactivity.TriggerAction(Of DependencyObject)
Protected Overrides Sub Invoke(parameter As Object)
Dim args = CType(parameter, MessageEventArgs)
MsgBox(args.Message.Body)
args.Message.Response = "View操作後のReturn"
args.Callback()(args.Message)
End Sub
End Class
'
'
' これより以下は、たぶん使いまわし(隠蔽)可能
Class Message
Public Property Body As Object
Public Property Response As Object
Public Sub New(body As Object)
Me.Body = body
End Sub
End Class
Class MessageEventArgs
Inherits EventArgs
Public Property Message As Message
Public Property Callback As Action(Of Message)
Public Sub New(message As Message, callback As Action(Of Message))
Me.Message = message
Me.Callback = callback
End Sub
End Class
Class Messenger
Public Event Raised As EventHandler(Of MessageEventArgs)
Public Sub Raise(message As Message, callback As Action(Of Message))
RaiseEvent Raised(Me, New MessageEventArgs(message, callback))
End Sub
End Class
Class MessageTrigger
' 参照設定: C:Program Files (x86)Microsoft SDKsExpressionBlend.NETFrameworkv4.5LibrariesSystem.Windows.Interactivity.dll
Inherits System.Windows.Interactivity.EventTrigger
Protected Overrides Function GetEventName() As String
Return "Raised"
End Function
End Class
XAML部分
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="100" Width="300">
<i:Interaction.Triggers>
<local:MessageTrigger SourceObject="{Binding Path=RequestShowMsgBox}">
<local:ConfirmAction />
</local:MessageTrigger>
</i:Interaction.Triggers>
<Grid>
<Button Content="Button" Click="Button_Click"/>
</Grid>
</Window>
tags: MVVMパターンもどき
posted in Program, VB.NET, WPF by ooltcloud | 1 Comment
2013年8月10日
WPF 扱うにあたって MVVM パターンをお勉強しておこうか…と思ったものの、思いのほか難しく半ば挫折したのでメモ(汗
元ネタはここ http://code.msdn.microsoft.com/windowsdesktop/MVVM-d8261534
元サイトの内容は、いろいろ凝ってて(計算処理が選べたり、DelegateCommand 実装したり、ラムダ式あったり、 yield return あったり、Generics あったり…と)、MVVM に行きつくまでの障壁が結構高い。
なので、超単純化してみました。単純化し過ぎて「これは MVVM じゃない」と言われると思うので「MVVM もどき」です(汗
- View(XAML)
特徴としては x:name 属性がないこと。
要するにコード側からは基本的にアクセスしない。
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="100" Width="400">
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding A}" Width="100"/>
<TextBlock Text="+"/>
<TextBox Text="{Binding B}" Width="100"/>
<TextBlock Text="=" />
<TextBlock Text="{Binding C}" Width="100"/>
<Button Content="計算" Click="CalcButton" Width="50" />
</StackPanel>
</StackPanel>
</Window>
- View(コードビハインド)
MVVM ではコードビハインドは原則使用不可。
Click イベント類は、コマンドオブジェクトにして XAML から 直接 ViewModel へ転送するらしい。
…けど面倒なのでコードビハインドを使用(汗
Class MainWindow
' ViewModel を New
Private _viewModel As ViewModel = New ViewModel
' View の DataContext へ viewModel をバインド
Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
Me.DataContext = _viewModel
End Sub
' 操作類は、viewModel 側のメソッドで実行させたいので、転送する。
Private Sub CalcButton(sender As Object, e As RoutedEventArgs)
_viewModel.Execute()
End Sub
End Class
- View-Model
View で表示するデータを置くところ。
View との結合は Binding で行い、直接コントロールは ViewModel からは操作しないようにする。
本来は、プロパティごとに PropertyChanged を発行する。そのために、ViewModelBase のような基底クラスを作ったりするようだが、今回の例では INotifyPropertyChanged を直接実装し、かつ、計算操作が行われたときに一括で更新するのみとした。
Imports System.ComponentModel
Public Class ViewModel
Implements INotifyPropertyChanged
Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) _
Implements INotifyPropertyChanged.PropertyChanged
' View に渡すデータ
Public Property A As Integer ' 入力1
Public Property B As Integer ' 入力2
Public Property C As Integer ' 計算結果
' 計算処理と View の更新
Public Sub Execute()
' 計算
C = Model.Calc(A, B)
' View を更新
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(""))
End Sub
End Class
- Model
計算処理本体。今回は Shared(Static) メソッド。
変哲もない、ただの足し算(汗
Public Class Model
Public Shared Function Calc(a As Integer, b As Integer) As Integer
Return a + b
End Function
End Class
tags: MVVMパターンもどき
posted in Program, VB.NET, WPF by ooltcloud | No Comments
2013年8月8日
相関サブクエリーといえば exists 述語ですが。
この exists 述語。ぐぐっても、使用例が概ね複雑(=相関クエリー)で理解が難しかったりするので、メモがてらまとめ。
exists とは 空集合(=∅)か、集合が存在するか(≠∅)を判定するための、関数らしきものです。
たとえば、以下のように記述すると EMP 表の全レコード数を表示します。サブクエリーが1件データを戻すからです。
SQL> select count(*) from EMP
2 where exists (select 1 from DUAL);
COUNT(*)
----------
14
しかし、以下のように記述すると 0 を表示します。サブクエリーが1件もデータを戻さないから(=0件だから)です。
SQL> select count(*) from EMP
2 where exists (select 1 from DUAL where DUMMY='A');
COUNT(*)
----------
0
要するに、exists とは集合に対する「is not NULL」のようなもの、だと思えばよいです。
exists は、非相関クエリーで使っても上記の通り結果は all or nothing にしかならないので、主に相関クエリーで使用されますが「exists = 相関クエリー」ではない点に注意です。
「やっぱりピンとこない」という場合は、以下と等価だと思ってもらっても OK です。(論理的には。実行速度とかは別の話。)
select count(*) from EMP
where (select count(*) from DUAL) <> 0;
COUNT(*)
----------
14
ちなみに Oracle の DUAL 表とはこういう表。
SQL> select * from DUAL;
DUMMY
-----
X
posted in Oracle, データベース by ooltcloud | No Comments
2013年8月6日
これまた Oracle 独特というわけではないですが。先の「Order by 句に Select 文」で相関サブクエリーが出てきたのでちょっと整理がてら。
相関サブクエリーとは、サブクエリー(子クエリー)に親クエリーの列名が出てくるタイプのサブクエリーです。
たとえばよくあるハマりどころとして。
Group by でグループごとの最大値を得ようとしたとします。
SQL> select JOB, max(SAL)
2 from EMP
3 group by JOB;
JOB MAX(SAL)
------------------ ----------
CLERK 1300
SALESMAN 1600
PRESIDENT 5000
MANAGER 2975
ANALYST 3000
ここまではいいのですが、「じゃあ誰が(どのレコードが)最大なんだ?」とか思って以下のように書いてもエラーです。
SQL> select JOB, max(SAL), ENAME
2 from EMP
3 group by JOB;
select JOB, max(SAL), ENAME
*
行1でエラーが発生しました。:
ORA-00979: GROUP BYの式ではありません。
ここで登場するのが相関サブクエリーです。以下のように書くと目的が達成できます。
SQL> select JOB, SAL, ENAME
2 from EMP a
3 where SAL = (select max(SAL)
4 from EMP b
5 where a.JOB = b.JOB);
JOB SAL ENAME
------------------ ---------- --------------
SALESMAN 1600 ALLEN
MANAGER 2975 JONES
ANALYST 3000 SCOTT
PRESIDENT 5000 KING
ANALYST 3000 FORD
CLERK 1300 MILLER
サブクエリー側の条件(where 句)に親クエリーの列名が出てきています。こういうのを相関サブクエリーと呼ぶらしいです。
また、今回の例だと、この where 句が Group by 句と同じ役割を担っています。
(ANALYST が複数行取得されているのは、同額の人が複数いるからですね)
ところでこの相関サブクエリー。手続き型言語(C#)で等価コードを書くとこんな感じ。
// 親クエリーのループ(from 句)
foreach (var a in EMP)
{
// 子クエリーの select の結果 (子クエリーの戻り値)
int maxSal = int.MinValue;
// 子クエリーのループ(from 句)
foreach (var b in EMP)
{
// 子クエリーの Where 句
if (a.JOB == b.JOB) //← a.JOB と同じ内容のものが集計対象になる
{
// max集計関数 (子クエリーの select)
if (maxSal < b.SAL) maxSal = b.SAL;
}
}
//-------------------------------------------
// 親クエリーの Where 句
if (maxSal == a.SAL)
{
// 親クエリーの select
Console.WriteLine("{0},{1},{2}", a.JOB, a.SAL, a.ENAME);
}
}
わりと手続き型そんまんまです。スコープも含めて。(上記コードでは null とか無視ですが)
なので、相関サブクエリーにぶち当たってわからなかったら、手続き型的に読み直して理解してみる、というのも手かもしれません。
posted in Oracle, データベース by ooltcloud | No Comments
2013年8月5日
別に Oracle 独特な話ではないですが…
某 SNS で 「Order By 句に Select 文が書けるのか?」という話題があったので調査。
結論としては「書ける」
たとえば以下のようなコードが書けます。
select * from EMP a
order by (
select b.ENAME from EMP b
where a.EMPNO = b.EMPNO -- EMPNO は Primary Key
);
で、これは普通に書くと、以下と同じ意味です。
select * from EMP
order by ENAME
ENAME 列でソートってことですね。
なぜ同じになるかというと、Order by 句で指定するものが、実は "列名" ではなく、"列のデータそのもの" だから。
要するに、Order by の "ENAME" は 実質的に "select ENAME from EMP" と同じ。
もっとも、直接 Order by に "select ENAME from EMP" を書くと直積になってしまうので、where 句で絞っています。
(直積以前に戻すデータはスカラーでないとダメですが)
なので、"order by 列名" は "order by (Select ~)" の糖衣構文だと思ったほうがよいかもしれません。
なぜならば、繰り返しになるけど Order by で渡っているものは、列名ではなく、ましてカラム番号でもなく、列のデータそのものだからです。
だからたとえば以下のような記述をすると、EMPNo の末尾1桁でソート、とかができる。
select * from EMP a
order by (
select mod(EMPNO,10) -- 末尾1桁
from EMP b
where a.EMPNO = b.EMPNO
);
結果 (EMPNO の末尾1桁でソートされる)
EMPNO ENAME
--------- ------------
7900 JAMES
7521 WARD
7782 CLARK
7902 FORD
7934 MILLER
7654 MARTIN
7844 TURNER
7566 JONES
7876 ADAMS
7698 BLAKE
7788 SCOTT
また、以下のような書き方もできたりします。
要するに、列名だろうと select だろうとなんだろうと、ソート対象になり得る列を生み出せればよいということですね。
select * from DEPT
order by (
case DEPTNO
when 20 then 1
when 10 then 2
when 40 then 3
when 30 then 4
end
);
結果 (then ? の ? 順でソートされる)
DEPTNO DNAME
------- ------------------
20 RESEARCH
10 ACCOUNTING
40 OPERATIONS
30 SALES
もっとも、こんな書き方しなくても…というのは多分ごもっともな気がするので、多用するのは禁物かもしれません(汗
p.s.
ところで当初、"order by (select n …"、の n がカラム番号なのかな?とか思って、
select * from EMP order by (select 2 from DUAL);
とか書いてテストしてみましたが…
エラーにこそならないものの 2 列目でソートされないし、それどころかソートされている列が見当たらない…
あたりまえですね。これだと、全行が "2" の列を作って、その列をソートして出力しようとしているだけなので、ソートされるわけがありませんよ…(汗 # もちろんエラーにもなりませんね_| ̄|○
posted in Oracle, データベース by ooltcloud | 1 Comment
2013年7月23日
引き続き、回帰分析。
プロットしたデータから、n次の関数の係数を求めます。
y(),x() がプロットデータ、degree が関数の次数。
行列の演算には、http://ooltcloud.sakura.ne.jp/blog/201307/article_22014635.html で作成したクラスを使用しています。
例によってエラー処理はしてません。(たとえば、x() と y() の要素数が一致しているかとか確認してません)
Public Class Regression
''' <summary>
''' 係数の取得
''' </summary>
Public Shared Function GetPolynomialCoefficients(y As Double(), x As Double(), degree As Integer) As Double()
Dim Ymax = y.GetUpperBound(0)
Dim Xmax = x.GetUpperBound(0)
Dim N = degree
' 二次元配列に移し替え
Dim matY(Ymax, 0) As Double
For i = 0 To Ymax
matY(i, 0) = y(i)
Next
' 次数に応じた x() の行列を作成
Dim matX(Xmax, N) As Double
For i = 0 To Xmax
For j = 0 To N
matX(i, j) = x(i) ^ j
Next
Next
' 回帰分析
Dim r = Analyze(matY, matX)
Return r
End Function
''' <summary>
''' 回帰分析
''' </summary>
Public Shared Function Analyze(matY As Double(,), matX As Double(,)) As Double()
Dim mat1 = Matrix.Transpose(matX)
Dim mat2 = Matrix.Multiply(mat1, matX)
Dim mat3 = Matrix.Multiply(mat1, matY)
Dim mat4 = Matrix.Inverse(mat2)
Dim mat5 = Matrix.Multiply(mat4, mat3)
Dim N = mat5.GetUpperBound(0)
Dim r(N) As Double
For i = 0 To N
r(i) = mat5(i, 0)
Next
Return r
End Function
End Class
使い方的には以下。
' プロットデータ
Dim x() As Double = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
Dim y() As Double = {5, 8, 7, 8, 9, 11, 9, 11, 13, 12}
' 回帰分析 (プロットデータから2次式の各係数を求める)
Dim r = Regression.GetPolynomialCoefficients(y, x, 2)
' 結果
Console.WriteLine("{2}x^2 + {1}x + {0}", r(0), r(1), r(2))
結果出力
-0.0189393939393945x^2 + 0.953787878787864x + 4.78333333333336
posted in Program, VB.NET by ooltcloud | No Comments
2013年7月22日
ちょっと行列計算が入用になったので作成。
Double の二次元配列の 左側添え字を行/右側添字を列と見立てて計算します。
エラー処理なし、逆行列の計算では行列が正則であるかどうかのチェックとかもなし。
使う予定がなかったので、スカラー積や和を求めるメソッドもありません(汗
Public Class Matrix
''' <summary>
''' 乗算
''' </summary>
Public Shared Function Multiply(multiplicandMatrix As Double(,),
multiplierMatrix As Double(,)) As Double(,)
Dim matA = multiplicandMatrix
Dim matB = multiplierMatrix
' 行数/列数確定
Dim L = matA.GetUpperBound(0)
Dim M = matA.GetUpperBound(1)
If M <> matB.GetUpperBound(0) Then
Throw New Exception("被乗数の列の個数と、乗数の行の個数が違います")
End If
Dim N = matB.GetUpperBound(1)
' 結果用
Dim matR(L, N) As Double
' 乗算
For i = 0 To L
For j = 0 To N
For k = 0 To M
matR(i, j) += matA(i, k) * matB(k, j)
Next
Next
Next
Return matR
End Function
''' <summary>
''' 逆行列
''' </summary>
Public Shared Function Inverse(regularMatrix As Double(,)) As Double(,)
Dim matA = regularMatrix
Dim N = matA.GetUpperBound(0)
Dim matR = E(N + 1)
For i = 0 To N
Dim a = matA(i, i)
' 除算
For j = 0 To N
matA(i, j) /= a
matR(i, j) /= a
Next
' 掃出し
For j = 0 To N
If (j <> i) Then
Dim b = matA(j, i)
For k = 0 To N
matA(j, k) -= matA(i, k) * b
matR(j, k) -= matR(i, k) * b
Next
End If
Next
Next
Return matR
End Function
''' <summary>
''' 単位行列
''' </summary>
Public Shared Function E(degree As Integer) As Double(,)
Dim N = degree - 1
Dim matR(N, N) As Double
For i = 0 To N
matR(i, i) = 1
Next
Return matR
End Function
''' <summary>
''' 転置行列
''' </summary>
Public Shared Function Transpose(matA As Double(,)) As Double(,)
Dim M = matA.GetUpperBound(0)
Dim N = matA.GetUpperBound(1)
Dim matR(N, M) As Double
For i = 0 To M
For j = 0 To N
matR(j, i) = matA(i, j)
Next
Next
Return matR
End Function
End Class
posted in Program, VB.NET by ooltcloud | 1 Comment
2013年7月19日
元記事はここ(http://ch3cooh.hatenablog.jp/entry/20130719/1374161266)。
近日中に同じシチュエーションに遭遇しそうなので考えてみました。
ただ、元記事の命題からは外れているかもしれません。とりあえず、
・画面右端から 20px
・テキストは 270°(-90°)回転
という条件でやってみました。
- Alignment とマイナス Margin で無理やり調整
とりあえず、サンプルの構成から変えず、プロパティの調整だけでなんとかなるかを実験。
なんとかなった!、けどクソコードだな…(汗、という結果に。
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid Background="Red" HorizontalAlignment="Stretch"
VerticalAlignment="Center" Margin="0,0,-1297,0"
RenderTransformOrigin="0.5,0.5" >
<TextBlock Foreground="Black" TextAlignment="Center"
FontSize="24"
Text="ここには可変長のテキストが入る" />
<Grid.RenderTransform>
<CompositeTransform Rotation="-90" />
</Grid.RenderTransform>
</Grid>
</Grid>
編集画面例
- Canvas で囲ってみた
無限長に可変する必要はないだろう、と勝手に考え、幅を 600px / 高さを 28px に固定。
回転する際、オブジェクト中央を中心に回転するわけなので、この回転軸が座標 (0,0) となるように Canvas.Top と Canvas.Left を設定。
そこから、Margin を使って、Canvas の左上ポイントと TextBox の左上ポイントが合致するように引き戻す。
あとは、それを Grid で囲って、Grid 側の Margin で 右 20px を設定。
・・・
一応それっぽくなったけど、設定多し。メンテ性悪そう。
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid Background="Red"
VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="0,0,20,0">
<Canvas Height="600" Width="28">
<TextBlock Width="600" Height="28"
Canvas.Left="-300" Canvas.Top="-14"
Margin="14,300,0,0"
RenderTransformOrigin="0.5,0.5"
TextAlignment="Center"
Text="ここには可変長のテキストが入る"
Foreground="Black"
FontSize="24">
<TextBlock.RenderTransform>
<RotateTransform Angle="-90" />
</TextBlock.RenderTransform>
</TextBlock>
</Canvas>
</Grid>
</Grid>
編集画面例
- 270°回転表示用のパネルを別に用意する
そもそも、Visio や Excel のように回転したオブジェクトを配置しているのではなく、配置したオブジェクトを回転させるような振る舞いなのが、そもそも無理を生じているわけですよね…というのに気づきまして(汗
そういうことなら、とりあえず配置自身は回転前にやっておいて、配置がすんだらそのパネルごと回転させればいいんじゃね?というのが以下。
つまり、回転させないオブジェクトを配置するパネルと、270°回転させるオブジェクトを配置するパネルをそれぞれ作って、重ねて表示すればよいのではと。(Azure 色が 270°回転表示配置用パネル)
大げさだけど、これが一番シンプルで基本に忠実な気がする…(汗
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid Background="Azure"
RenderTransformOrigin="0.5,0.5"
Margin="660,250,-440,250">
<Grid Background="Red"
HorizontalAlignment="Center" VerticalAlignment="Bottom"
Margin="0,0,0,20">
<TextBlock Foreground="Black"
FontSize="24"
Text="ここには可変長のテキストが入る"/>
</Grid>
<Grid.RenderTransform>
<CompositeTransform Rotation="-90" />
</Grid.RenderTransform>
</Grid>
</Grid>
編集画面例
posted in Program, xaml by ooltcloud | No Comments
2013年7月15日
先(http://ooltcloud.sakura.ne.jp/blog/201307/article_15211613.html) のつづき。
先の例では、グリッドパネルの表示エリア一杯に描画のグラフを表示したので、グラフの拡大縮小と、表示位置の移動を行ってみます。
まず、描画エリアの Grid を ScrollViewer で囲みます。そして Grid に "View" という名前をつけます。
<ScrollViewer>
<Grid x:Name="View">
<Path x:Name="Graph" Data="" Stroke="Red" Stretch="Fill" />
</Grid>
</ScrollViewer>
拡大/縮小の指定をどうやって指示するかですが、今回は Slider を使用し ValueChanged イベントで値の変更を知ることとしました。また、拡大縮小の最小値は 0.1, 最大値を 1000 としました。
<Slider x:Name="Zoom" Value="1" Maximum="1000" Minimum="0.1"/>
次に、ValueChanged イベントを書きます。
Graph.Data プロパティ (Geometry クラス) の Bounds プロパティに、現在設定している Path の描画領域に関するデータが記録されています。今回は描画領域の高さがほしいので Height プロパティを参照します。
Slider の Value 値が拡大率なので、前述 Height (=Path データの高さ) と sender.Value (=Slider の Value) を乗算し、その値を Grid の Height (=View.Height) に設定します。
Private Sub Zoom_ValueChanged(sender As Object ...
View.Height = Graph.Data.Bounds.Height * sender.Value
End Sub
こうすると、スライダーで拡大縮小、スクロールバーで上下位置の移動が可能になります。
・スライダーを操作し拡大

・さらに拡大

・スクロールバーを操作し表示領域を変更
posted in Program, VB.NET, WPF by ooltcloud | No Comments
2013年7月15日
WPF の XAML で関数グラフを描いてみる実験。
XAML で数式を設定すると勝手にグラフを描いてくれるような方法あるのでは?…と期待して調べたのですが、早々に断念(汗
結局、古典と同じく直線近似で描くのが現実的ではないかという結論に。
# ベジェで描く方法もあるようですが、私の頭がついていきませんです…(汗
描く方法として、Polyline と Path のどちらにしようかと思いましたが、今回は描画後に端点を動かすとかは考えないので Path で描くことにしました。
- XAML 側
Data プロパティはコードでセットするので空にしておきます。
描画したグラフは、Grid パネル全体に描画したいので、Path の Stretch は Fill にしておきます。
<Grid>
<Path x:Name="Graph" Data="" Stroke="Red" Stretch="Fill" />
</Grid>
- コードビハインド(VB) 側
パスマークアップ文を構築します。
初回だけ M(移動)コマンドでポイントを移動させ、以後は L(線)コマンドで前回のポイントとの直線を引いていきます。
数学のグラフでは一般的に第一象限は右上ですが、Path で指定する座標系は第一象限が右下の領域なので、関数の結果 y は座標に変換する際に -y とします。
そうして作成したパスマークアップ文を、StreamGeometry.Parse メソッドによって Path の Data プロパティにセットします。
Private Sub Draw()
Dim xfrom As Decimal = 0D ' 開始 x 座標
Dim xto As Decimal = 10D ' 終了 x 座標
Dim pathData As String = ""
' 開始座標から終了座標までの範囲を 1000 分割して求める
For x = xfrom To xto Step (xto - xfrom) / 1000D
' y = f(x) を求める
Dim y = Math.Sin(x)
' 区間の直線を描く
If (x = xfrom) Then
pathData &= String.Format("M{0},{1} ", x, -y)
Else
pathData &= String.Format("L{0},{1} ", x, -y)
End If
Next
' 描画
Graph.Data = StreamGeometry.Parse(pathData)
End Sub
- 実行結果
参考) パスマークアップ構文
http://msdn.microsoft.com/ja-jp/library/ms752293.aspx
posted in Program, VB.NET, WPF by ooltcloud | 2 Comments
2013年7月4日
posted in 勉強会 by ooltcloud | 1 Comment
2013年5月30日
「すごい広島 #2」に参加してきました。
http://atnd.org/events/39927
atnd をみると、「すごい Haskell」本に関連した何かかという感じですが、実際のところはもくもくでした。ルールは以下ようなことらしい。
http://great-h.github.io/
行ってみて Haskell 的な何かがあればそれでもよいし、なければ SQL Server 回りの調べものとかしたかったのでそれでいいやと思っていったのですが、SQL Server の参考書を持ち込むのを忘れて早々に撃沈(汗
んでは、使ってるマシンの再セットアップなどを…と思ったけど、現地で AC を確保できなかったのでこれまた撃沈。次点で、TortoiseGit 的な…と思ったのですがなんとなく食指が動かず…
途方に暮れたところで、(この直前にも GitHub のパスワード忘れて件でいろいろ途方に暮れてましたが)、ルールによればやったことを blog 記事を書けということだったので、とりあえず blog をみるとコメントスパムが 4000 件… おいおい(汗
てことで、これをまずは整理しますか、ということで、まずはスパムの削除をすることに。
でもこれは、すぐに済む予定だったんですよ… しかし結果としては終わりませんでした(汗
コメントはデフォルトで 20件 ほど表示されていまして、そこで削除していけばいいんですが、20/4000 = 200回削除ボタンを押すのか?やってられねー、ってことで、だったら表示件数増やせばいいんじゃね?ってことで 表紙件数を 999 件に変更しました。この辺で今日の私の運が尽きた…
コメントスパム 999件 表示させて削除をしようとしたら、こんなの出ました。

URL が長いんですと。いまでも URL って2048 文字とかそういう制限あるんでしたっけ?とか思ったものの、まあいいやというこど 500件に変更。再度削除すると、こんどはこんなのが…

なんでやねん…_| ̄|○
ここから少しずつ件数を少なくして行って、エラーがでなくなる件数を探る戦いに…
紆余曲折ありましたが、結果としては
- 70件以上 →確実に不可
- 50件前後 →エラーが発生したりしなかったり
- 20件前後 →まあ大丈夫
といった感じで、結局デフォルト(20件前後)で削除しないと安定して削除できないという結果に…(汗
なんでそんなことになっているんでしょ(汗
そもそも、Capcha もどきのプラグイン入れているのにコメントスパムが通るという仕様ってどうよ。まあこのあたりの実装をちゃんと確認しろということなのでしょうが…(汗
そんなことで、今日のところは、Nonce, Please! (http://www.yuriko.net/arc/2008/07/07/nonceplease100/) というプラグインをいれて様子を見るかということで、作業を終了しました。
posted in 勉強会 by ooltcloud | 1 Comment
2013年1月29日
Windows のユーザーとパスワードの検証。
以前、SecureString で怪しげなことを書いていますが、ユーザーとパスワードの検証だけであれば、PrincipalContext を使用することで検証できるようです。
- 事前準備
System.DirectoryServices.AccountManagement を参照設定し、import する。
- ローカルアカウントの場合
Dim p = New PrincipalContext(ContextType.Machine)
MsgBox(p.ValidateCredentials("username", "password"))
- ドメイン (Active Directory) アカウントの場合
Dim p = New PrincipalContext(ContextType.Domain)
MsgBox(p.ValidateCredentials("username", "password"))
参加ドメインや自マシンに対する検証は上記で OK ですが、参加以外のドメインや他マシンのアカウントの検証を行う場合は、PrincipalContext コンストラクタの第二引数にコンピューター名等を指定します。
posted in Program, VB.NET by ooltcloud | No Comments
2013年1月15日
Visual Studio 2005(*1) で Visual Source Safe 6.0 (以下VSS6) を使用していると文字化けすることがあります。
たとえば時折、こんなダイアログが表示されたりします。

対策としては、以下のようなことが言われているようです。
- 文字化けが発生する行の行末を、漢字(=マルチバイト文字)ではなく、シングルバイト文字(=ASCII)にします。
- 具体的には、コメントなどで行末が漢字で終わる場合には、行の最後に必ずホワイトスペースを補うようにします。
この現象は、VSS6 が UTF-8 に対応していないことに起因します。
ある条件が成立したとき、VS6S はソースコードをチェックインするとき、行末の「0D-0A(CR-LF)」を「0D 0D-0A(CR CR-LF)」と CR を一つ余分に記録してしまいます。
メカニズムは以下のような感じです。
例えば以下の文字があるとします。
あいう[改行]
UTF-8 では以下のように記録されます。
E3-81-82 E3-81-84 E3-81-86 0D-0A
ところが VSS6 はこのバイト列を Shift-JIS だと思って処理します。
Shift-JISでは、第一バイトが 0x80~0xFF の場合は2バイト文字だと判断します。なので VSS6 は上記バイト列は以下のように見えます。
E3-81 82-E3 81-84 E3-81 86-0D 0A
このため、最後の改行文字「0D-0A (CR-LF)」が泣き別れます。(0Dを第二バイトだと誤認識する)
この結果、改行文字が「0A (LF)」だけであるように見えます。VSS6 はチェックインの際、これを自動的に補って「0D-0A (CR-LF)」にします。
E3-81 82-E3 81-84 E3-81 86-0D 0D-0A
この VSS6 にチェックインしたソースコードを、Visual Studio がリロードすると前述のダイアログが表示されます。なぜならば VSS6 によって修正されたバイト列を UTF-8 としてみると、「0D 0D-0A (CR CR-LF)」と CR 単独の改行コードがあるように見えるからです。
E3-81-82 E3-81-84 E3-81-86 0D 0D-0A
この段階で、上記ダイアログで「はい」を押すと、改行コードが標準化(=CR+LF)されるため以下のようになります。
E3-81-82 E3-81-84 E3-81-86 0D-0A 0D-0A
この結果、空行が一行増えます。
ちなみにここで、改行が無駄だからと改行を削除してしまう最初に戻ってしまうため、同じことを繰り返してしまいますので、それはしてはいけません。
これは、行末尾にある連続したマルチバイト文字が奇数バイトの場合に発生します。具体的にはコメントなどで漢字が末尾にある場合に発生します。
しかし、末尾が漢字であれば必ず発生するわけでしありません。発生しない場合は行末の連続したマルチバイト文字が偶数バイトである場合です。また、行末がシングルバイト文字の場合は発生しません。
このようなことから、「末尾にスペースをいれておくと化けない」という対策になっていたりします。
また、VSS6 で文字化けしたソースコードを一括で修正したい場合は、(OD OD-0A) を (20 0D-0A) に置き換えることで、文字化けを一掃できます。
もっとも今更 VSS6 を使うな、という話もありますが…
(*1) 別に Visual Studio 2005 でなくても 2008 でも 2010 でも再現します。たぶん…
posted in 開発環境 by ooltcloud | 2 Comments
2013年1月15日
posted in Program, VB6, 開発環境 by ooltcloud | 3 Comments
2013年1月13日
Windows 上の Oracle でパスワード認証ではなく OS 認証によるユーザーを作るには、以下のようにします。
create user "OPS$PCNAMEUSERNAME" identified by externally;
grant CONNECT to "OPS$PCNAMEUSERNAME"
PCNAME というのはコンピューター名で、USERNAME は OS認証の対象としたい Windows のユーザー名です。
OPS$ というのは OS 認証のための接頭辞で、デフォルトは OPS$ です。以下で確認できます。
show parameter OS_AUTHENT_PREFIX;
注意点としては全て大文字で記述することです。コンピューター名やユーザー名に小文字が入っていたとしても大文字で書く必要があります。でないと認証してもらえません。
また、OPS$USERNAME、も不可です。Linux 系はそれで OK かもしれませんが(未確認)、Windows ではコンピューター名が必要です。
更に、コンピューター名とユーザー名を で区切る必要があるため、必ずダブルクォーテーションでくくる必要があります。
Oracle のユーザー名は 30 文字が上限なので、接頭辞~ユーザー名までが 30 文字で完結するようにする必要もあります。
ユーザー名が "OPS$PCNAMEUSERNAME" なので、スキーマ名も当然 "OPS$PCNAMEUSERNAME" となります。したがって、スキーマ名を指定してオブジェクトを指定したい場合は、
select "OPS$PCNAMEUSERNAME".TABLE1
となります。かっこわり…(汗
といった感じなので、OS 認証を使う場合は、接続用のユーザーとオブジェクトがあるスキーマは分け、接続用のユーザー(スキーマ)にはオブジェクトは置かないようにした方がよい気がしますね…
posted in Oracle, データベース by ooltcloud | No Comments
2013年1月11日
ストアドアウトラインによる実行計画の固定のメモ。一応 10g までが対象。(11g からは SPM)
例題として、現在、INDEX UNIQUE SCAN を行う以下の問い合わせがあったとします。
SQL> select * from emp where empno=999;
実行計画
---------------------------------------------------
Plan hash value: *********
----------------------------------------------
| Id | Operation | Name |
----------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| EMP |
|* 2 | INDEX UNIQUE SCAN | PK_EMP |
----------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("EMPNO"=999)
この問い合わせの実行計画を INDEX UNIQUE SCAN ではなく、TABLE ACCESS FULL となるように変更したいとします。
手順は以下。
- ヒントなしのアウトラインを作成します。
-- ヒントなしのアウトラインを作成
create or replace outline NO_HINT
ON
select * from emp where empno=999;
- TABLE ACCESS FULLとなるようヒントを指定した時のアウトラインを作成します。
-- ヒント指定のアウトラインを作成
create or replace outline SET_HINT
ON
select /*+ full(emp) */ * from emp where empno=999;
- 双方のヒントを入れ替えます。(*1)
-- ヒントの入れ替え
update outln.ol$hints
set ol_name = decode(ol_name,'SET_HINT','NO_HINT','NO_HINT','SET_HINT')
where ol_name in ('SET_HINT','NO_HINT')
;
commit;
- ストアドアウトラインを有効にします。(*2)
alter system set USE_STORED_OUTLINES=TRUE;
このようにすると、ヒント句なしで問い合わせを実行しても、TABLE ACCESS FULL を選択するようになります。(*3)
(実行計画レポートの note のところに ストアドアウトラインを使用しているという表示が出ます。)
SQL> select * from emp where empno=999;
実行計画
--------------------------------------------------
Plan hash value: *********
----------------------------------
| Id | Operation | Name |
----------------------------------
| 0 | SELECT STATEMENT | |
|* 1 | TABLE ACCESS FULL| EMP |
----------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("EMPNO"=999)
Note
-----
- outline "NO_HINT" used for this statement
-
HINT の内容がどのようなものか確認したい場合は、たとえば以下。
col OL_NAME for A10
col HINT_TEXT for A60
select
OL_NAME, STAGE#, HINT#, HINT_TEXT
from
OUTLN.OL$HINTS
where
OL_NAME='NO_HINT'
order by
STAGE#, HINT#;
-
ストアドアウトラインに登録されている SQL 文を確認したい場合は、たとえば以下。
select
NAME, SQL_TEXT
from
DBA_OUTLINES;
-
11gR1 (11.1.0.6 for Win x86) では動作しませんでした。(アウトラインが無効になっている感じ)
10gR2 (10.2.0.1 for Win x86) / 11gR2 (11.2.0.1 for CentOS x86) では期待通り動作。
# いずれも OS は日本語、DB の文字セットも日本語(JA16SJIS または JA16SJISTILDE)で確認。
posted in Oracle, データベース by ooltcloud | No Comments
2013年1月11日
SQL*PLUS 上でバインド変数の使い方のメモ。
-- 変数の定義
var A varchar2(10);
-- 変数の代入
begin
:A := 'X';
end;
/
-- 変数の使用
select DUMMY from DUAL where DUMMY=:A;
ちなみに、入力を求める場合は「& + 変数名」を使用します。
SQL>select DUMMY from DUAL where DUMMY=&入力値;
入力値に値を入れてください:
posted in Oracle, データベース by ooltcloud | No Comments
2013年1月11日
以下のようなコードで Powershell で ODP.NET を使用して Oracle にアクセスすることが可能です。
[System.Reflection.Assembly]::LoadWithPartialName("Oracle.DataAccess")
$connstr = "User ID=****;Password=****;Data Source=****"
$conn = New-Object Oracle.DataAccess.Client.OracleConnection($connstr)
$conn.Open()
$cmd = New-Object Oracle.DataAccess.Client.OracleCommand
$cmd.Connection = $conn
$cmd.CommandText = "select * from **** where **** = :t"
$cmd.Parameters.Add(":t", "****")
$reader = $cmd.ExecuteReader()
while ($reader.Read())
{
$reader["****"].ToString() + " " + $reader["****"].ToString()
}
$cmd.Dispose()
$conn.Close()
$conn.Dispose()
posted in Oracle, PowerShell, Windows, データベース by ooltcloud | No Comments
2013年1月11日
NOARCHIVE モードで運用中(オンライン中)のデータベースを VSS(Volume Shadow Copy)を使用してバックアップを取ってみました。
結論としては、(テストでは)バックアップ開始時点のデータを問題なく戻すことができました。(*1)
注意点としては、バックアップする際に忘れずにオンライン REDO ログをバックアップし、リストアの際にオンライン REDO ログも戻すようにします。(*2)
メカニズムは以下です。
-
VSS を使用したバックアップを開始すると、Windows によってスナップショットがとられます。
このスナップショットは「クラッシュ整合状態」と言われ、要するに電源を引き抜いた後(電源遮断時)のハードディスクの状態と同じです。
この状態のものがバックアップとして取られます。
-
この VSS で取得したバックアップファイルをリストアすると、クラッシュから復旧したのと同じ状態なので、Oracle はクラッシュリカバリーを実行します。
これによってデータファイルがリカバリーされ、バックアップ開始時点のデータが戻ります。(*3)
もっとも、NOARCHIVE モードでは、
- オンライン中のデータベースを VSS を使ってバックアップ
- クラッシュ後の、一貫性のない(制御ファイルとデータファイルのSCNが異なる)状態でのバックアップ
を公式にサポートしていません。従って、このような運用は避けるべきです。(*4)
NOARCHIVE モードでの VSS を使用した正しいバックアップの取り方は以下。
- バックアップ前に、一度正常に Shutdown する。
- VSS を使用し、バックアップを開始する。
- バックアップが開始された(スナップショットが取得された)ことを確認後、データベースを再起動する。
このようにすれば、バックアップの終了を待つことなくデータベースの再起動ができるため、ダウンタイムが最小かつ一貫性のあるバックアップが取得できます。
-
しかし 100% 成功するとは限らないと思います。
例えば、多重化された制御ファイル間の不整合でデータベースがリカバリーできないなどの障害が発生するかもしれません。
-
正常に shutdown(abort 以外)してから取得したバックアップの場合は、クラッシュリカバリーは不要であるため、オンライン REDO ログは不要です。
-
クラッシュリカバリーでは、必須でバックアップ開始時点のオンライン REDO ログファイルが必要です。
-
というか、どこまでのデータを保全しないといけないか、という視点で考えれば、このようなバックアップにほとんど意味がありません。バックアップの設計を考え直した方が無難です。
posted in Oracle, データベース by ooltcloud | No Comments
2012年12月26日
Oracle Database をバックアップするには、以下で表示されるファイルを、Shutdown (Shutdown Transactional) で Database を停止した後に、エキスプローラー等でコピーします。
V$ビューより
-- 制御ファイル
select name from v$controlfile;
-- データファイル
select name from v$datafile;
-- tempファイル (*1)
select name from v$tempfile;
-- Online REDO (*2)
select member from v$logfile;
-- 初期化ファイル (SPFILE)
show parameter spfile;
上記以外に <ORACLE_HOME>database フォルダにある以下のファイルをコピーします。
- 初期化ファイル (PFILE) (*3)(*5)
init<SID>.ora
- パスワードファイル (*3)(*6)
pwd<SID>.ora
-
temp ファイルはなくても自動生成されるので取得しなくてもよい。
-
Online REDO は基本的には不要。(一貫性のある状態で Shutdown されているはずだから)
但し、Online REDO をリストアしない場合は、以下の手順で立ち上げる必要があります。
startup mount
recover database until cancel;
alter database open resetlogs;
-
<ORACLE_HOME> は、環境変数、または、レジストリから特定します。
環境変数に登録がない場合は、以下のレジストリにエントリーがあります。
HKEY_LOCAL_MACHINEsoftwareoracleKEY_<ORACLE_HOME_NAME>ORACLE_HOME (*4)
-
<ORACLE_HOME_NAME> は「OraDb11g_home1」のような名前。
スタートメニューまたは UniversalInstaller で確認。
-
init<SID>.ora を開くと、SPIFILE の場所が書かれている場合があります。
-
パスワードファイルは、"sys"ユーザーなどの管理者パスワードが記録されているっぽい…
posted in Oracle, データベース by ooltcloud | No Comments
2012年12月18日
Oracle の データベース(インスタンス)の状態は、shutdown, nomount, mount, open の 4 つがありますが、よくこの状態遷移をさせるコマンドをよく忘れるのでメモ。
また、現在のデータベースの状態の確認は以下のように入力します。
select STATUS from v$instance;
データベースの状態と対応する表示は以下。
データベースの状態 |
STATUS |
shutdown |
エラー (ORA-01034: ORACLE not available) |
nomount |
STARTED |
mount |
MOUNTED |
open |
OPEN |
posted in Oracle, データベース by ooltcloud | No Comments
2012年12月17日
SQLPlus を使用していて、たまに文字化けしたメッセージを見ることがありますが。
SQL> startup open
ORA-32004: ?????????(????????)???????????????
ORA-01081: ???????Oracle???????? - ???????????????
これは、英語のメッセージのようで。環境変数 NLS_LANG を AMERICAN_AMERICA にしてやると見えるようになります。
(SQLPlus を一度終了して、「SET NLS_LANG=AMERICAN_AMERICA」を実行します。host コマンドではだめです。)
SQL> startup open
ORA-32004: obsolete and/or deprecated parameter(s) specified
ORA-01081: cannot start already-running ORACLE - shut it down first
ちなみに上記のメッセージは nomount 状態でのメッセージで、mount 状態に移ると、正しく日本語で表示されます。
SQL> startup open
ORA-32004: 廃止または使用不可(あるいはその両方)のパラメータが指定されました。
ORA-01081: すでに稼働中のOracleは起動できません - まずシャットダウンしてください
上記の文字化けは、この日本語部分が ? として表示されているようです。
posted in Oracle, データベース by ooltcloud | No Comments
2012年11月4日
IE9 で表示した場合、同じ font-family:sans-serif; 指定であるにも関わらず、保存されている html ファイルの文字エンコーディングによって、選択されるフォントが異なってしまうようです。
試験コードは以下。
<span style="font-family:sans-serif; font-size:32pt">
既定のプログラム<br>
IJKLMN<br>
△○×÷∫<br>
</span>
上のコードを Shift-Jis で保存した場合の表示。

上のコードを UTF-8 で保存した場合の表示。

保存したエンコーディングの差で表示が異なってしまっています。
Shift-Jis で指定した場合、"MS Pゴシック" が表示されますが、UTF-8 の場合は "Arial" になるようです。
但し、"Arial Unicode MS" ではないようなので、"△"や漢字は "MS Pゴシック" が充てられている模様です。
てことで、IE9(IE系?) の場合、文字エンコーディングによっても選択されるフォントが異なる場合があるので要注意です。
posted in Program, WEB, 情報技術, 文字 by ooltcloud | No Comments
2012年11月3日
IE9 と 他のモダンブラウザ(っていうの?) で、font-family 指定の解釈に違いがあったのでメモ。
たとえば以下のような指定をします。
<div style="font-family:'dummy', 'Times New Roman', 'MS PMincho'; font-size:24pt;">
PS/2 - USB 変換コネクタ
</div>
dummy は存在しないフォント名の代わりに指定。
次に欧文フォント名('Times New Roman')を指定し、最後に和文フォント名('MS PMincho')を指定します。
こうすると、期待する結果としては、欧文は'Times New Roman'、和文は'MS P明朝'で表示されるはず。
で、実際表示してみると、Firefox16 では期待通りになりました。

ところが IE9 では、和文フォントが'MS Pゴシック'になってしまいます。

どうやら IE9 では font-family を複数指定した場合、最初に見つかったフォントのみを採用し、そのフォントにない文字はデフォルトフォント (='MS Pゴシック') で表示する、ということのようです。
なので、IE9 では、欧文と和文のそれぞれにフォントを指定する、といった指定は出来ないので要注意です。
posted in Program, WEB, 情報技術, 文字 by ooltcloud | No Comments
2012年11月1日
IE9(IEシリーズ?) で font-family を serif にしておくと、表示されるフォントが難儀なことになってしまうようです。
具体的には以下のような指定がされているとき。
font-family:serif;
例えば以下のような文字列を表示する場合に。
区点コード(16区)漢字
亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱宛姐虻飴絢綾鮎或粟袷安庵按暗案闇鞍杏以伊位依偉囲夷委威尉惟
IE9では以下のように見えます。

セリフ(明朝体系)で表示させています。しかし、一部の字はサンセリフ(ゴシック体系)になっているし、ちゃんとセリフになっているものもよく見ると字形がおかしい(「漢」とか)
理由を調べたところ、概ね以下のような流れでした。
- serif で指定する。
- MSP明朝ではなく、なぜか Batang(韓国語フォント) が割当たる。
- Batang には「ー」(長音)とか「区」「亜」のグリフがない。
- グリフがないものは、ブラウザデフォルトのフォント(既定ではMS Pゴシック)が割りあたる。
- 表示が腐ったことに。
twitter のサイトのフォント表示がおかしいものもこれと同じ理由ですね。
ということで、セリフ系の文字が使いたい場合は、IE系ブラウザー対策として、font-family を指定するとき、筆頭に「'MS PMincho'」を入れておく必要がある、ということのようです。
font-family:'MS PMincho',serif;
というか、セリフ系のデフォルトを IE がちゃんと持っていさえすればこんなことには…(汗
posted in Program, WEB, 情報技術, 文字 by ooltcloud | No Comments
2012年11月1日
「テンソル積」という文字らしい。
⊗
点検報告書用図記号で使うために、似た記号をかつて外字で作っていました。今後外字を作らずに済みそうです。もちろんこの記号は「テンソル積」っていうくらいだから、本来の用途はちがうのだと思いますが…
ところで電気屋的にはこの記号見ると、次にほしいのはこれだよね。
⦿◉
これは、前者を「丸中黒」、後者を「蛇の目」と呼ぶようです。
原典はここから。
http://ja.wikipedia.org/wiki/JIS X 0213非漢字一覧
posted in 情報技術, 文字 by ooltcloud | No Comments
2012年10月30日
http://ooltcloud.at.webry.info/ からこちらに移転しました。
まだまだサイトの整備が終わっていませんが、とりあえず表示フォント問題に目処がついたので正式運用を始めてみます。
posted in 移転 by ooltcloud | No Comments
2012年9月16日
前回、「クロージャーに渡した変数がスコープ外になった時の値が表示される」とか書いたわけですが、それは本当なのか?
たとえば以下。
private void button1_Click(...)
{
int i=1;
Action f = () =>
{
MessageBox.Show(i.ToString());
};
// button1_Click内で実行
f.Invoke();
// button1_Click内の後で実行
Dispatcher.BeginInvoke(f);
// i を変更
i = 10;
}
これは、f.Invoke(); では 1 がちゃんと表示されます。Dispatcher.BeginInvoke(f); のほうは予定通り 10 で表示されます。
ではこれでは?
private Action f;
private void button1_Click(...)
{
int i=0;
f = () =>
{
i += 1;
MessageBox.Show(i.ToString());
};
}
private void button2_Click(...)
{
f.Invoke();
}
private void button3_Click(...)
{
Dispatcher.BeginInvoke(f);
}
最初の1回のみ button1_Click() を実行し、button2_Click() , button3_Click() を適当に実行します。するとどうなるか?インクリメントしていってますよね?
要するに、キャプチャされた変数 (今回の場合は i ) は別に親のスコープから外れたときに固定化されるのではなく、
・変数の実体 (値) を参照化 (ボクシング処理) し、
・その参照を無名関数 (上記の場合、f) が所持する。
ということをしていそうです。
だからもっとひどいことをすればこんなこともできる。
private Action f1;
private Action f2;
private void button1_Click(...)
{
int i=0;
f1 = () =>
{
i += 1;
MessageBox.Show(i.ToString());
};
f2= () =>
{
i += 100;
MessageBox.Show(i.ToString());
};
}
private void button2_Click(...)
{
f1.Invoke();
}
private void button3_Click(...)
{
Dispatcher.BeginInvoke(f2);
}
関数を変えても、参照した変数 i は同じなので、f1 と f2 で i は共有されています。だから、同じ実体 (=i) に対して、f1 を実行すれば +1 , f2 を実行すれば +100 されていきます。
tags: クロージャー怖い
posted in C#, Program by ooltcloud | No Comments
2012年9月16日
以下のコードは、WPF系のフレームワーク(WPF/Windows Phone/Win8) を想定しています。Winforms や Consoleでは動作しないので注意。
C# や VB.net で 無名関数(ラムダ式?) を作るとき、無名関数ではなく、無名関数を定義した側の変数を参照することができます。クロージャーと呼ぶらしいです。例えば以下。
private void button1_Click(...)
{
int i = 1;
Dispatcher.BeginInvoke
(
() =>
{
MessageBox.Show(i.ToString());
}
);
}
結果は 1 が表示されます。無名関数の部分は緑マーカーの部分ですが、赤マーカー部分の設定が表示されています。要するに(無名)関数の本来のスコープから外れたところの値を、引数で渡すとかすることなく、参照できてしまうわけです。
ところでこのクロージャー。便利ですが、いろいろ罠があります。
private void button1_Click(...)
{
for (int i=0; i<5; i+=1)
{
Dispatcher.BeginInvoke
(
() =>
{
MessageBox.Show(i.ToString());
}
);
}
}
上記のコードの場合、for で 5回ループさせて、そのループ変数をさせようとしたつもりなので、結果は 0→1→2→3→4 と表示されそうですが、そうはなりません。 5回表示されますが、表示される数字は全て 5 です。
なんでさ。
また、上記のコードの for が抜けてから i = 10; を入れると、5 回の表示すべてが 10 となってしまいます。
private void button1_Click(...)
{
int i;
for (i = 0; i < 5; i += 1)
{
Dispatcher.BeginInvoke(
() =>
{
MessageBox.Show(i.ToString());
}
);
}
i = 10;
}
for の外で代入した数値がなぜ!!
そもそも、当初のもくろみとしては 0→1→2→3→4 と表示したかったはずです。クロージャーを使うと実現できないのでしょうか。
できます。
以下のように書けばいいです。
private void button1_Click(...)
{
for (int i = 0; i < 5; i += 1)
{
int a = i;
Dispatcher.BeginInvoke(
() =>
{
MessageBox.Show(a.ToString());
}
);
}
}
この結果からみると、要するに、クロージャーに渡した変数がスコープ外になった時の値が表示される。ということがいえそうです。(*1)
(*1)
最後のコードで、for の ループ変数 i と、for ループ内の int a のスコープは違います。
ループ変数 i は次回ループでもそのインスタンスが継続して使用されますが、a のほうはループごとに新しいインスタンスが生成されている点に注意です。
tags: クロージャー怖い
posted in C#, Program by ooltcloud | No Comments
2012年9月11日
SecureStringというものがあるらしいことを知る。これを使って、パスワードが渡せるらしい。
これと、Process.Start を組み合わせることで、RunAs のようなことができる。
Dim pw As New System.Security.SecureString
For Each ch In "pass".ToCharArray()
pw.AppendChar(ch)
Next
Dim p = System.Diagnostics.Process.Start("c:test.exe", "user", pw, "")
RunAs コマンドと違うところは、パスワードもスクリプト内に仕込めてしまうところ。ある意味便利。危険だが…
あと、この手を使って、Windowsアカウントそのものをユーザーリストにした、認証サーバーもどきが作れるなあと思うなど。ダミーの exe を用意して、実行権限を設定しておき、その exe が起動できるかどうかで、入力されたユーザー/パスワードが正当な権限を持っているかどうかが判断できる、的な。
パスワードリストを自前で管理したくないときはいいかもしれないな… # まっとうな方法で認証すべきでしょうが、そのやり方がいまだに分からないので…(汗
posted in Program, VB.NET by ooltcloud | 1 Comment
2012年3月28日
PowerShell では Alias が設定されているため、コマンドプロンプト時代の DIR や CD コマンドが使えます…と思ったら火傷の元で、思ったように動かず変な罠にはまったりします。
たとえば、コマンドプロンプトで
CD C:WINDOWS
CD
DIR /W
とした場合の結果は以下ですが。

同じことを PowerShell 上で実行すると以下のようになります。

先頭の「CD C:WINDOWS」は OK です。正しくディレクトリに移動します。(実はこれも厳密には嘘。後述)
次の「CD」はエラーは出ません。が、コマンドプロンプトでは表示されたカレントディレクトリが表示されません!
そして最後の「DIR /W」に至っては、エラーが出てしまいます。
なぜかと言えば、CD も DIR もとあるコマンドレットのエイリアスであって、厳密に CD や DIR をエミュレーションしているわけではないからです。

CD は Set-Location のエイリアスです。したがって、カレントディレクトリの設定はできるものの、カレントディレクトリの表示はしません。カレントディレクトリを表示する場合は、別のコマンドレット Get-Location が担当です。
DIR は Get-ChildIetm のエイリアスです。しかし、Get-ChildIetm には /W なんてオプションは渡せないのでエラーになってしまいます。
また、CD は カレントディレクトリの設定なら万事 OK かというとそうではなくて。
たとえば C:WINDOWS にいるときに、CD D:、とかやるとコマンドプロンプトと Powershell とで結果が変わります。
なので、結局エイリアスといっても、コマンドプロンプトと同じようには動いてくれないので、できるだけあてにしないほうが吉です。でもコマンドが長すぎる!と思うなら、
Get-Location は GL
Set-Location は SL
Get-ChildItem は GHI
とかあるようなので、こちらに慣れたほうがよさそうです。
しかし、画面消去は「CLEAR-HOST」と書くよりは「CLS」のほうが好きかな。パラメータ指定がないために、コマンドプロンプトと差が出ないので。
改めてエイリアスにチよるのは怖いなと思ったのでまとめてみました。
ただ、エイリアスはよく使うコマンドレットの一覧という側面があると思うので、どんなコマンドが定義されているか、一度は眺めて知っておくと、PowerShell がより使いやすくなる気がします。
posted in PowerShell, Windows by ooltcloud | No Comments
2012年3月11日
Windows 7 になってからなのか、気づけば Wordpad の保存形式が rtf 以外も選べるようになっていました。

rtf だと 画像を貼り付けるとファイルサイズが肥大化しましたが、docx だと画像が圧縮されて肥大化しにくいです。なので、Office やツール類をインストールできない PC で画面キャプチャを大量に取得しないといけない場合とかでは、Wordpad を使用するというのは良い選択肢になりそうです。
posted in Utility, Windows by ooltcloud | No Comments
2012年3月8日
ここ (http://ooltcloud.sakura.ne.jp/blog/201203/article_07001033.html) の続き。
Excel 2003 の互換色に何があるかを確認したい場合、Excel 2003 を持っていなくても、Excel 2010 上で確認することが可能です。
具体的には、「ファイル」メニュー→「Excelのオプション」→「保存」タブ→「ブックの外観の保持」セクションの「色」ボタンを押すことで確認できます。

(図1) 「ブックの外観の保持」セクション
「色」ダイアログでは、Excel 2003 と同じ色パレットが表示されます。

(図2) 「色」ダイアログ
「色」ダイアログで、任意の色を指定し「変更」ボタンを押すと、「色の設定」ダイアログが表示されます。

(図3) 「色の設定」ダイアログ
いくつか試してみればわかりますが、Excel 2003 の互換色は、色の設定の「標準」タブにある色のどれかです。(「色」ダイアログで選択した色が、白いヘキサカーソルで選択されます)
なので、互換色と標準タブの色の対応を記憶して設定、というのがテーマ問題も無視できるので、これが王道ではないかと思います。もっとも記憶できればですが…
結局、互換色を設定する方法は色々あるわけですが、互換色を使い続けるためにはかなりの労力が必要です。また、互換にとらわれず Excel 2007 以降の新しい思想(=テーマ)にのっとった配色を心掛けたほうがメリットが大きいと思います。
なので、どうしても互換色が必要だと状況を除いては、互換の維持は気にしないほうがよいと思います。
posted in Excel, Office by ooltcloud | No Comments
2012年3月7日
前回 (http://ooltcloud.sakura.ne.jp/blog/201202/article_22005600.html) の記事で Excel 2003 互換色を設定する方法を書きましたが、この方法だと、配色(テーマ)を変更すると色が変わってしまいます。

(図1) 互換色の配色で色設定したところ

(図2) 配色を別のものに変更したみたところ
ちょっと面白くないですね。
確実に色を変えたくない場合は、色コードを指定すれば良いのですが、さすがに面倒くさいです。

(図3) 色コードによる指定の例
残念なことに、この問題については良い方法が見つかっていません。
しかし、たとえば以下のようにすれば、テーマ情報を削除することが可能です。
1.新しいワークブックを作成する。
2.色コードを固定したいセルをコピーし、.新しいワークブックに、
「形式を選択して貼り付け」→「コピー元のテーマを使用してすべて貼り付け」
を選択する。
3.新しいワークブックに貼り付けた箇所を元のワークシートに書き戻す(コピー&貼り付けをする)
具体的には以下のような感じです。

(図4) 「形式を選択して貼り付け」を選択

(図5) 「コピー元のテーマを使用してすべて貼り付け」を選択
すると以下のようにテーマを変更しても、色が変わらなくなります。

(図6) テーマを変更する前。左列,右列ともに同じ色

(図7) テーマを変更してみたところ。左列は色変わりするが右列は色替わりしない
(右列は「コピー元のテーマを使用してすべて貼り付け」を行った列)
注意点としては、「コピー元のテーマを使用してすべて貼り付け」でテーマ情報が削除されるのは、他のブックへの貼り付けに対してです。コピー元のブック内で同操作を行ってもテーマ情報は削除されません。
したがって、色を固定するためには、他のブックヘのコピーして、その結果をもとのブックへ貼り付けなおしてやる必要があります。
また、他のブックへの貼り付けであれば、コピー元とコピー先のテーマが一緒でも、「コピー元のテーマを使用してすべて貼り付け」で、テーマ情報は削除されます(=色は固定されます)
posted in Excel, Office by ooltcloud | 1 Comment
2012年2月22日
VB2010 (.net 4.0) から Tuple 型というのがあるようです。
どうも、元々は F# で複数の値を戻すための実装のようですが、VBでも使用できる模様。
たとえば以下のように書けば複数の値を戻せるようです。
Function func() As Tuple(Of String, Integer, Double)
Return Tuple.Create("aaa", 1, 2.0)
End Function
Sub Main()
Dim a = func()
Console.WriteLine("{0} {1} {2}", a.Item1, a.Item2, a.Item3)
End Sub
メソッドから複数の値を戻すとき、戻り値用のクラスや内部クラス (Class内に書くClass) を別に作る必要がなく、引数参照渡し (Call by Reference) に頼らずに済むので便利そうです。
個人的には、引数参照渡しによる戻り値は、隠れグローバル変数になってしまったり、引数のうちどれが戻るのかが一目でわからないので好きでなかったんですね。
かといって複数の値を返すメソッドが出る都度、クラスを書いていくのもどうか…と思っていて。
Tuple はそれを解決できるので、今後積極的に使ってみようと思う所存です。
ただ、プロパティ名が Item1…とか無機的な名前で、その名前について個別に xml コメントをつけるとかそういうことができるわけではないようです。
なので、戻り値として受けた Tuple は直後に正規の変数に代入しかえてやるとかの配慮が必要。それを忘れると(Tuple を戻すメソッドと 、その Tuple を参照する場所が離れすぎると)、その Tuple の .Item1 が何の値なのかコード上で追いにくくなってしまうので、その点は注意でしょうか。
なお、本件の元ネタはここから拝借しました。
posted in Program, VB.NET by ooltcloud | No Comments
2012年2月22日
Excel2010で色を設定すると、互換性チェックのダイアログが表示されます。
これは、Excel2003以前では使用しなかった色が Excel2010 で設定できることに起因しています。(と思う)
他方、まだ Excel2003 と互換を強く持ちたい文書もあるので、Excel2003 でもメンテナンスできる色を設定したい場合があります。ところが、Excel2010 では Excel2003 と互換がとれる色は、無彩色を除けば(多分)赤と黄の2色しかありません。
これではちょっと困る、といった場合、webを検索すればいろいろな方法が出てきます。
しかし、完全互換を目指さず、よく使っている色に限定するのであれば、以下のような方法で比較的簡単に Excel2003 互換パレットを作成することができます。
1.「ページレイアウト」タブ → 「テーマ」セクションの「配色」ボタン → 「新しい配色パターンの作成」を選択。
2.「新しい配色パターンの作成」ダイアログで、テキスト濃色2, 淡色2, アクセント1~6 の色を以下のように設定。

設定するカラーコードの一覧
|
R |
G |
B |
テキスト/背景 濃色2 |
51 |
51 |
51 |
テキスト/背景 淡色2 |
150 |
150 |
150 |
アクセント1 |
0 |
0 |
255 |
アクセント2 |
255 |
255 |
0 |
アクセント3 |
255 |
0 |
255 |
アクセント4 |
0 |
255 |
0 |
アクセント5 |
0 |
255 |
255 |
アクセント6 |
255 |
204 |
153 |
3.すると、カラーダイアログで Excel 2003 と互換する色が選択できるようになります。

先頭行 … すべて (白/黒/40%灰/80%灰/青/黄/マゼンタ/明るい緑/水色/ベージュ)
二行目 … 2,5,6,8,9列目 (50%灰/アイスブルー/アイボリー/薄い緑/薄い水色)
三行目 … 5,6列目 (グレー/薄い黄)
六行目 … 5-9列目 (濃い青/濃い黄/紫/緑/青緑)
先頭行は、ほぼ純色系で全列使えます。
その他の行は、使えるところと使えないところがあるので注意です。Excel 2003 以前ではよく使われていたであろう、薄い緑/薄い水色/薄い黄、は二行目~三行目にあります。赤は標準色を使います。
大体これで、贅沢言わなければある程度は互換が取れると思います。
ここに出ている以外の色が使いたい場合は、使わない色の列をその色に変えるか、新しい配色パターンを設定します。
注意点としては、テーマ(?)として設定されているので、テーマまたは配色パターンの変更をしてしまうと、セルの色も変わってしまう点です。
それと、Excel 2003 カラーが Excel 2007 以降、排除されたのにはそれなりに理由がある(かもしれない)ので、特に互換を意識しないといけないということ以外では、互換カラーは使わないほうがよいのかもしれません。(個人的には純色好きなんですけどね…)
posted in Excel, Office by ooltcloud | 1 Comment
2011年10月13日
ディレクトリを移動する際に使用できるメソッドとして、
System.IO.Directory.Move(formDir,toDir)
がありますが、これは同一ドライブでの移動のみに対応していて、ディレクトリのコピーや他のドライブへの移動はできません。
ところが、ディレクトリのコピーを行う
System.IO.Directory.Copy(formDir,toDir)
のようなメソッドは用意されていません。なんでやねん…_| ̄|○
なので web ページを探ると、「Copyメソッドはありません」「ないので諦めて作りましょう(ファイルを一つ一つ再帰的にコピー)」って書かれているところも多いですが、VB2005以降だと、
My.Computer.FileSystem.CopyDirectory(formDir,toDir)
が用意されていてディレクトリのコピーが可能です。
でも my は VB2005 以降でしか使えません。しかし my はショートカットのはずなので、元のクラスがあるはずです。とおもって探したら、以下にありました。
Microsoft.VisualBasic.FileIO.FileSystem.CopyDirectory(formDir,toDir)
たぶんこれで、VB2003以前でも使用できると思います。
(試していません。 私はもう .net 1.1は使うことはない予定…)
しかし、my でなくても使用できるということは、VBでなくても、C#でも使用できるのでは?
参照設定で、「Microsoft.VisualBasic」を追加する必要がありますが、以下の記述で使用できました。
Microsoft.VisualBasic.FileIO.FileSystem.CopyDirectory(formDir,toDir);
C#でVBのライブラリなんて…という抵抗感もありますが、属性もコピーしてくれるので楽ですよ。
posted in C#, Program, VB.NET by ooltcloud | No Comments
2011年10月12日
パーティション表のパーティション・キーを更新する場合、デフォルトでは
ORA-14402: パーティション・キー列を更新するとパーティションが変更されます。
とエラーがでますが、これを回避する場合は、
ALTER TABLE ENABLE ROW MOVEMENT;
としておけばよい模様。
もっとも、「パーティションが変わる=行全体を別のパーティションにコピーしかえる」ことになるから、コストが高くなるので、本当に必要かどうかは要検討。
posted in Oracle, データベース by ooltcloud | No Comments
2011年9月21日
オフラインでもインストールできるインストーラーは、以下の ftp サイトからダウンロードできるみたいです。
ftp://ftp.adobe.com/pub/adobe/reader/win/
posted in Utility by ooltcloud | No Comments
2011年8月16日
インターバルパーティションなテーブルを作成してみたので、その時のメモ。
-- インターバルパーティションなテーブルを作成
create table INTERVAL_TEST(
DTM timestamp primary key,
MSG varchar2(50)
)
partition by range(DTM)
interval(
NumToDSInterval(1,'MINUTE')
)
(partition values
less than(
to_date('2011/01/01','YYYY/MM/DD') -- このパーティションは削除(Drop)できない
)
);
-- パーティションあたり格納行数の収集
begin
dbms_stats.gather_table_stats(
ownname => 'SCOTT',
tabname => 'INTERVAL_TEST',
method_opt => 'FOR ALL COLUMNS SIZE 1',
cascade => true);
end;
/
-- パーティションの確認/および格納行数の確認
select TABLE_NAME,PARTITION_NAME,TABLESPACE_NAME,HIGH_VALUE,NUM_ROWS
from USER_TAB_PARTITIONS;
-- パーティション名の変更
alter table INTERVAL_TEST rename partition SYS_P41 TO DATE_2011_01_01_00_00;
-- パーティションの移動
alter table INTERVAL_TEST move partition DATE_2011_01_01_00_00 tablespace TEST;
-- パーティションの削除
alter table INTERVAL_TEST drop partition SYS_P42;
posted in Oracle, データベース by ooltcloud | No Comments
2011年8月16日
最近、blog とかの表示で、○とかの記号が小さく表示されているのをよく見るようになりました。
普通、慣れた処理系だとこんな感じに見えるものが、
ブログとかでは、こんな感じで見えてしまうわけです。
よく見ると、「○」は小さくなっていますが、「★」は小さくなっていないんですね。
なんでだろう?
ぐぐると、「UTF-8 でフォント指定をしていないサイトを IE7 で表示した場合」に発生する事象」的な感じで、IEのバグっぽい記事が多いのですが、それにしては、iPad とか非 MS 環境でも、○が小さい事例は見かけるんですね。
で、とあるブログの表示をコピーして Excel に貼り付けてみると、フォント名が Arial Unicode MS になったので、それでいろいろいじってみたところ。
欧文だけを並べるとこんな表示に。
なんか自然です。単純に、欧文フォント幅(日本的には半角に近い)で統一されているって感じです。特に、インテグラルについては、和文フォントよりもらしいわけで…
もしかしてフォントに言語区分(?)みたいなのがあって、共通記号(○×とか数学記号とか)は欧文ベースの字形(フォント幅)が採用されていて、そうでない地域ローカルな記号は、その地域の字形(フォント幅)が採用されている、ということなんだろうか…
ちょっとこの件は継続的に調査ということで。
posted in 情報技術, 文字 by ooltcloud | No Comments
2011年8月15日
何かの役に立つ気がするのでメモ。
監査の登録
begin
DBMS_FGA.ADD_POLICY(
OBJECT_SCHEMA => 'SCOTT',
OBJECT_NAME => 'EMP',
POLICY_NAME => 'SCOTT_EMP'
);
end;
監査の削除
exec DBMS_FGA.DROP_POLICY('SCOTT', 'EMP', 'SCOTT_EMP')
監査の結果
select EXTENDED_TIMESTAMP,SQL_TEXT,SQL_BIND
from DBA_COMMON_AUDIT_TRAIL
where DB_USER='SCOTT';
posted in Oracle, データベース by ooltcloud | No Comments
2011年8月15日
GIMP Poertable で TIF が開けない!なぜ?
あれ、と思って JPG をなら開けるだろ?と思って試すがこれもだめ!どうしてー?
と思ったら、GIMP Poertable 本体の Path に日本語が入っているとだめな模様…_| ̄|○
# 画像ファイルの Path に日本語があるのは良い。この差は一体…
posted in Utility by ooltcloud | No Comments
2011年8月15日
OEM (Oracle Enterprise Manager) っていろいろ面倒なようなのですが。
ある日突然、IPアドレスもコンピューター名も変更していないのに、立ち上がらなくなったりするのでその時の対策メモ。
たとえば、起動で以下のようなメッセージが出ます。
C>emctl start dbconsole
OC4J Configuration issue.
<ORACLE_HOME>/oc4j/j2ee/OC4J_DBConsole_<hostname>_<ORACLE_SID> not found.
フォルダがない、と言っているのですが、仰る通りフォルダがないのです。
なんで?と思うと、ちょうど<hostname>のところにホスト名があって、これが原因っぽい。
そして、<ORACLE_HOME>/oc4j/j2ee/ フォルダをよく見ると、ちょうど<hostname>の箇所がコンピューター名になっているフォルダはありますね、と。
なにをしましたか?というと、そういえば hosts に自分のホスト名をコンピューター名とは違う名前で追加したなあ…
とりあえず hosts からそのエントリーを外して、再度 start dbconsole をすると動く…
つまりですね。OEM は 自分の host 名を得るときに、hosts に定義があると、コンピューター名よりも hosts のほうを優先すると…
なんとなく Windows をやっているとコンピューター名が最優先っぽく感じるわけですが、そうではないというのが落とし穴でありまして… TCP/IP 的には当然なんでしょうが。
そんなわけで OEM 環境下では hosts や DNS のような名前解決まわりのメンテに気をつけよう…
そして、前回の自ホスト名の確認は何に使ったかといえばこのためでして…_| ̄|○
posted in Oracle, データベース by ooltcloud | No Comments
2011年7月27日
以下のコードで、自ホスト名を取得できます。
import java.net.InetAddress;
import java.net.UnknownHostException;
public class gethost {
public static void main(String[] args) {
System.out.println("hostname =" + getHostName());
}
public static String getHostName() {
try {
return InetAddress.getByName(
InetAddress.getLocalHost().getHostAddress()
).getHostName();
} catch (UnknownHostException e) {
return "";
}
}
}
冗長だ。
return InetAddress.getLocalHost().getHostName();
でいいはずだ。と言われればその通りですが…
後者だと、windows の場合、必ず computername が取得されるのですが、前者のコードだと、hosts に記載している hostname が取得できます。hosts に記載してなければ、(AD環境だとFQDNな)コンピューター名が取得できます。 # もっとまっとうな方法があるのかもしれないが…
posted in Java, Oracle, データベース by ooltcloud | 1 Comment
2011年7月19日
早いものでiPad2 が我が家に来て2か月ですが、使用感を少しまとめ。
・予想通り重かった。
絶対重量としては軽いのでしょうが、書籍と比較するとやはり重い。
片手で軽々、という感じではなく「ずし」っときます。
女性とかだと肩を悪くしそう。
・思いのほかよく落ちる。
アプリケーションが時折サクっと落ちる。昔の Mac の様。
結構な頻度で落ちるので結構びっくり。
現在閲覧メインなのであまり問題ないけど、編集とかしてたらキレてます。
・入力がつらい
タッチ操作って案外つらい。
文字入力は想定内でしたが、それ以外にも以下のようなことがつらい。
・思った箇所のリンクをうまく押せない。
・変なところを不意にさわってしまい、別のページやアプリに飛んでいく。
そして戻ってこれない。
・BSを押そうとして確定を押してしまう。
そしてパスワードエラーとなって、それまでの入力がおじゃんになる。
・文字をコピーしようと思っても、思ったところを選択できない。
・メニューの出し方がわからない。(アプリでまちまち)
・セキュリティ的にやばい
パスコード一発で、あとはアクセスフリーという設計はいかがか?
アプリの起動に対して一切のセキュリティがかからない。
基本的にマルチユーザーで使うものではない、というのはわかるが…
他人に特定の資料をみせるために、iPadごと渡そうものなら以下略…
せめて2段階のセキュリティは必須ではないかと。
・アプリのお試しが難しい
まず探すのが大変。
そして、使ってみようにも安いとはいえ、有料即決済ってのはちょっと壁。
買ってみるといまいちだったということもかなりある。
・JavaApplet も動かないのはつらいなあ…
いや、ネットワーク経由な KVM な都合で…
なんか悪いところばかり列挙のようだが、よいところといえば、
・ブログの読み込みが楽になった。
・Twitter や Facebook を割と運用できるようになった。
とでしょうか。やはりお手軽起動、重いとはいえ片手で支えられ、操作に机が必要ないというのは、対閲覧にはかなり強い。PC とは雲泥の差。
翻って、やはり編集用途としては、私の場合は PC から置き換わるものではないようなので、当面はネットブックやノート、デスクトップマシンから離れるということはなさそうです。
posted in ハードウェア by ooltcloud | No Comments
2011年7月19日
DBCAで新規にデータベースを作成しようとしたら、ORA-00444 が発生して、データベースが作れなくなった。
エラーメッセージがORA-死死死って感じだったので慌てふためいたのだが、なんのことはない、プロセス数の入力でデフォルトの 150 から 10 に変更していたのが原因だった。
って、エラーが発生することがわかっている数値が入力できるってのやめよーよ…_| ̄|○
posted in Oracle, データベース by ooltcloud | No Comments
2011年5月13日
iPad2 を購入しました。
よく考えてみると、初appleです。かつて、会社で Mac に出会い、Macintosh Centris 650 がほしくて手が出ず、LC2 あたりで買おうかと思っていたのに、なぜか PC自作 の道に走り以後 Windows …
その後も iMac mini とか iPod nano とか惹かれたけど購入するには至らず、iPad は発売直後に買おうと思っていたのに、出遅れて買いそこね、iPad2 が出たら予約してでも速攻で買うぞと待ち構えていたら、発売延期になり…
Apple とは縁がないのかなあと思っていましたが、4月下旬に予約し、ついに入手しました。苦節(?)約20年(笑
とりあえず当分の間 iPad2 で遊ぶ予定です。
posted in ハードウェア, 散財 by ooltcloud | No Comments
2011年5月6日
オブジェクト初期化子の書き方と、匿名クラスの書き方のメモ。
Sub Main
' オブジェクト初期化子
Dim s = New aaaa With {.Value1 = 100D}
' 匿名クラス
Dim r = New With {.value1 = 100D, .value2 = 200I}
End Sub
Class aaaa
Public Value1 As Decimal
Public Value2 As Integer
End Class
posted in Program, VB.NET by ooltcloud | No Comments
2011年5月5日
最近、想定外なんてありえない、的な話をよく聞く。「想定外を言い訳にするな」とか「想定されていないわけがない」とかそういう使われ方をしている模様。個人的には、この意見の意図するところが理解できなかったので少し考えてみたところ、「想定」という語のとらえ方に違いがあるのでは?という結論に達した。
つまり、「想定」という語に2つの意味が込められていると予想。1つは「"起こり得る可能性があるかどうか"を少なくとも思いつくことができたか」、もう一つは「設備の設計として、どこまでを耐えるものとしたか」だ。便宜上、前者を「可能性想定」、後者を「設備想定」と呼称することにする。(学術的に正確な語があったらすみません)
おそらく、「想定外の事態」と述べる人は設備想定を指して述べており、「想定されていないわけがない」と述べる人は可能性想定を指して述べているのではと。だとしたら、話がかみ合うわけがない。
…ところで、設備想定は現実に実現可能な(特にコストに縛られて)決定される。したがって、可能性想定はされているから、可能性想定のすべてが設備想定に反映されていてしかるべき、という意見はあまり意味を持たないと思う。
たとえば、自宅でサーバーをたて、24時間運転したいとする。最初に脅威に思うのは(バグとかネットワークとかを除けば)電源だ。停電したら即困ってしまう。なので、最近は家電量販店にも UPS なる無停電電源装置が売られているので、これで停電に備えようと考えたとする。すると問題は解決するか?
実は解決しない。問題を電源関係に限定したとしても。
なぜならば、UPS 自体が故障することがありうるから。現実に、1次側の給電は正常なのに2次側の給電がされなくなるというトラブルはありうるし、事実よくある。また、電源装置(ATX電源とか)そのものが故障する可能性がある。電源装置は、ハードディスク等の回転機系に次いで壊れやすい。
これに対応するにはどうするか。よくやるのは、電源が二重化されているサーバーを購入し、その片側を商用電源に直につなぎ、片側を UPS につなぐ。そうすると、UPS が故障のしたとき、商用電源は生きているから停電しない。商用電源が停電した時は UPS が給電し、電源装置が片側故障しても、もう片側が受電する。
それではこれで万全か、というとそうでもない。UPS の電源容量は限られているから停電が長期になった場合には対応できない。それではどうするか、たとえば自家用発電機を用意したりする。もちろん自家用発電機も発電能力に限界があるから、継続して燃料を供給する必要がある。ということは、燃料の輸送経路や輸送手段の確保も必要だ。それ以前にサーバーの置き場が火事(全焼事故)になったらどうするのか、その場合は別の建屋にバックアップサーバーを用意する必要が出てくる。では大規模災害が発生した時には?バックアップサーバーは別の遠い土地へ用意する必要が…
可能性想定を追い求めればこのループはまだまだ続く。もっとも上述程度であれば最近はレンタルサーバーだのクラウドサービスなどがあって、それなりに安価に対応できたりするが、要は可能性想定を突き詰めていけば、きりがないのだ。そもそも自宅でサーバーを立てようとして、電源の信頼性を高めようとしただけなのに、可能性想定を追い求めてしまうと、その時点で発散して収束することがない。
個人のサーバーにそこまでの可用性が必要なのか?という指摘は至極全うだが、しかし詰まる所企業レベルでも国家レベルでも問題は変わらない。なぜならば可能性想定をすべて満足する実現可能な解などありえないからだ。結局、可能性想定のどこかまでを対策として設備に反映するよりほかに方法がない。もちろんそれは議論してしかるべきだ。だから、「UPSが壊れることを(設備)想定に入れると、サーバーの価格が高価になり購入できない(あるいは損益分岐を超えてしまう)。なので、UPSの稼働は前提とし、あくまで商用電源の瞬停のみをフォローする」というのは一つの判断だ。しかし、その結果 UPS が壊れたり、建屋が火事になってサービス停止した時、設備屋として述べられることは、その可能性について想定していたとしても「想定外の事態」と述べる他ないわけだ。
したがって、設備屋は、なぜそれが設備想定外とされたのか?いう話や、今後設備想定に入れるべきかどうかという話題には対応できるかもしれないが、「想定外なんてありえない」とか責められても答えようがないと思う次第。
posted in 与太話 by ooltcloud | No Comments
2011年5月2日
検索しようとして、「使いにくくなったなグーグル」と思ったので、そのまま入力しググらせたら、すでに 2ch にその件でスレが立っていた…
「Google インスタント検索」という機能らしく、一応設定で回避できる模様。「オプション(画面右上の歯車アイコン)→検索設定」
インクリメンタルサーチすればいいってものではないと思うんだが…
ついでに ie9 の検索ワードと url を同じ場所に入力、というのも違和感があるのでなんとかしてほしい。
posted in 与太話 by ooltcloud | No Comments
2011年4月18日
IEEE1284 な拡張カード(私の場合は ExpressCard でしたが)を VMWare (Workstation 7) 上で使用するにあたり、ちょっと苦労があったのでメモ。
結論から述べると、拡張カードを挿してドライバーをインストール後(ホスト OS 上で LPT ポート の認識を確認したら)、VMWare を再インストールする必要があります。
再インストールしない場合、仮想マシンの設定で LPT ポートが選択でき、ゲスト OS にも LPT ポートが現れても、いざパラレルポートに接続しようとすると「VMparport ドライバを開くことができません」的なメッセージがでて、ゲスト OSから LPT ポートに接続できません。
なぜそうなるかは不明ですが、まあハードウェア変わったら再インストールってことで良いのではないでしょうか、といったところで気にしないことにしました。--;
posted in ハードウェア, 仮想化, 遺産 by ooltcloud | 2 Comments
2011年4月17日
先の記事の ExpressCard の動作実験をしてみました。
ホスト OS はExpressCard を LPT3 として認識。仮想OS側はLPT1 として認識し、LPT3 へリダイレクト、という設定で確認しました。仮想化プラットフォームは VMWare Workstation 7 を使用。
|
ホストOS
(物理PC)
|
仮想OS
(VMWare)
|
備考
|
COPY test.txt LPTn |
○
|
○
|
LPTポートへのファイル出力
(PC-PR201互換プリンタへの出力) |
SENTINEL/RAINBOW |
未確認
|
○
|
プロテクト ドングル
(パラレルポートタイプ) |
Xilinx ISE 12.4 (iMPACT) |
未確認
|
○
|
パラレル JTAG(?) ケーブル
(CPLDへのダウンロード) |
諸般の都合で ISE や プロテクトドングルを使うソフトウェアをホスト OS にインストールして確認することができませんでしたが、仮想 OS 側からも問題なく掴めているのでホスト側でも問題ないのではと思います。
基本的にだめかと思っていましたが、やってみるとできるもんですね。まあマザーボード直結のIEEE1284にできることのすべてのケースに対応できるわけでもないだろうから油断は禁物ですが。
posted in ハードウェア, 仮想化, 遺産 by ooltcloud | No Comments
2011年4月12日
前に USB-IEEE1284 では LPT として認識されない、という件で。
> [遺産対策] USB-IEEE1284変換ケーブル
USB-IEEE1284 ケーブルを 2本買って使えないという情けないことになり、非常に悔しかったことなどもあるので、なにがなんでも LPT ポートとして認識するやつ!ということで探して購入してみました。
# もはや使用するかどうかではなく、LPTポートを作ることが目的になっている…(汗

メーカー不明、型番不明(?)のにくいやつで、PCI Expess 接続の IEEE1284 カードです。販売元では、KF-EC9901-GB-1P、という型番がついていますが、カード本体には一切メーカー名や型番の刻印等がありません…
Moschip 社製の MCS9901 というチップを積んでいるようで、ExpressCard ではない、普通の PCI Express カードの IEEE1284 カードでも使用されているチップのようです。たとえばこれとか。
ExpressCard タイプの IEEE1284 は現在確認できたものは例外なくカード側が DB26 (Dsub 26pin 3列) で、そこから、DB25 (Dsub 25pin 2列) への変換ケーブルが付属しています。「ツライチだったら邪魔にならなくていいのになあ」とか思うわけですが、そんなものは発見できず…
しかしはやり恐るべきは、形状は全く一緒でも中身が Prolific 製チップということがあり、こちらのタイプは ExpressCard でも 接続はUSB経由で、そしてLPTとして認識しません。(印刷サポートとして認識。要はUSB-IEEE1284 ケーブルと同じ)。外見からでは全く判別できないので、購入時は要注意です。
なので、LPTポートがほしい場合には、Moschip を採用したカードかどうかを目安にして選択すると良いような気がします。(Prolific の場合は不可)
posted in ハードウェア, 遺産 by ooltcloud | 1 Comment
2011年4月11日
日本語入力関連で、覚えておくと便利なアクセラレートキーを列挙。
便利、というか、いつのまにかモードが変わってしまってよく慌てるので…(汗
[CTRL] + [SHIFT]
IME を変更する。
たとえば、ATOK ←→ MS-IME の切り替え。
[ALT] + [かな]
ローマ字入力 ←→ かな入力変換。
[CTRL] + [SHIFT] + [かな]
非IME時のカナロック ←→ カナロック解除。
多分IME2003以前、あるいは ATOK(2004) で有効。
IME2007 または IME2010 では、非IMEなカナロックにならない模様(IME モードに入る)
posted in Windows, 環境設定 by ooltcloud | No Comments
2011年4月9日
環境変数の devmgr_show_nonpresent_devices を 1 に設定しておくと、デバイスマネージャーで現在接続していないデバイスを表示することが可能のようです。
方法。
1.環境変数 devmgr_show_nonpresent_devices を 1 にする。※
※ 「システムのプロパティ」画面の環境変数を選択し、ユーザーまたはシステムのどちらかに
変数名 : devmgr_show_nonpresent_devices
変数値 = 1
を設定する。
2. デバイスマネージャーを起動する。
3.「表示」→「非表示のデバイス表示」を選択する。
以上の手順で、今現在接続していないが、システムに記録されているデバイスが一覧できます。
要らないNICを削除したり、COMポート番号をどれだけ使っているか確認するのに便利。
posted in Windows, 環境設定 by ooltcloud | No Comments
2011年3月25日
上が Vsiual Studio 2010 Professional。下がVisual Basic 2010 Express。


微妙にせこい。ターゲットCPUの変更ができない。
そのくらいさせてよって感じ。
もっとも VB2005Express は最適化の選択もできなかったから、それに比べればマシですが…
posted in Program, VB.NET, 開発環境 by ooltcloud | No Comments
2011年3月25日
ここの続報
春の情報処理技術者試験が、初夏の情報処理技術者試験になった模様です。
http://www.jitec.ipa.go.jp/1_00topic/topic_h23_tokubetsushiken.html
しかし名称がややこしいことに…>平成23年度特別情報処理技術者試験(仮称)
まあ中止でなく延期になったということは、喜ばしいと思う。
ところで日程が割れるんですね。
これって、両方受けるとか可能なんでしょうか?併願OKだったら受けちゃうんですけど。
採点日程が従来より詰まっているので、ダメなんだろうけど。
posted in 時事, 資格 by ooltcloud | No Comments
2011年3月21日
posted in 時事, 資格 by ooltcloud | 1 Comment
2011年3月20日
ここの続き
今どきのマザーボードには、34pin FDD コネクタがついていないってことで、それではしばらくの間困りそう…ということで、自宅用の FDD 探しを実施。
しかし、ショップを巡ってみると、FDD は内臓/USB 共に軒並み販売終了状態。あっても三千円級以上ということで、さすがに年に数回使用する程度の頻度でその値段はなー、と思っていたら、最寄りのじゃんぱらで約1000円のドライブを大量に発見。新品ではなく中古ですが。

IBM の CN533 と呼ばれる機体のようで、調べてみると 3mode でもあるらしい。今までショップで発見した奴は軒並み 2mode であったので、これはいいやと購入。
繋いでみると、「TEAC FD-05PUB USB Device」と認識。TEACかあ。PC8801FHの時代は大変お世話になりました。
ちゃんと1.2MBのフロッピーも認識して、VMWare 上の Windows2000 から 1.2MB のフォーマットも無事できました。
てことで、とりあえず自宅用の FDD は確保ということで。
posted in ハードウェア, 遺産 by ooltcloud | No Comments