2015年7月26日日曜日
Microsoft Natural Ergonomic Keyboard 4000ズーム機能をスクロールに
Microsoft Natural Ergonomic Keyboard 4000というキーボードを使用している。
このキーボードは中央にズームレバーがあるのだが、コレをスクロールに変えられないかと思った。
調べてみると"C:\Program Files\Microsoft IntelliType Pro"という検索結果がヒットしたがそんなものは存在せず、探したところ"C:\Program Files\Microsoft Mouse and Keyboard Center"がその設定箇所であった。
ここのcommands.xmlをいじることでズームをスクロールに変更できる。
あとは
となっているところを
と書き換えれば良さそう。
2015年2月1日日曜日
WPFのComboBoxでTextが正常に更新されない
WPFにおいてIsEditable="True"に設定したComboBoxを使用することがあるかと思います。
そのようなComboBoxで日本語入力を行った際に、ComboBoxのTextプロパティ(およびバインドしているプロパティ)の値が更新されないという状況が発生しました。
いくつかの環境で試したところ、Win8.1・MS-IME,Win7・MS-IME,Win7・Google日本語入力では正常に動作し、Win8.1,Google日本語入力という環境下のみで発生するバグのようです。
TSF関連はバグの温床なのでやはり闇がそこらじゅうに埋もれてそうです。
幸いにも、ComboBoxのTextChangedで無理矢理値を書き換えることで修正が可能です。
TextChangedイベントは次のXAMLかコードビハインドによって設定できます。
参考:http://stackoverflow.com/questions/6914942/how-do-i-get-textchanged-events-from-an-editable-combobox
TextChangedEventArgs.OriginalSourceプロパティはイベントを発生させた大本のElementを取得できるので、ComboBoxのPart_EditableTextBoxを取得できます。
そのようなComboBoxで日本語入力を行った際に、ComboBoxのTextプロパティ(およびバインドしているプロパティ)の値が更新されないという状況が発生しました。
いくつかの環境で試したところ、Win8.1・MS-IME,Win7・MS-IME,Win7・Google日本語入力では正常に動作し、Win8.1,Google日本語入力という環境下のみで発生するバグのようです。
TSF関連はバグの温床なのでやはり闇がそこらじゅうに埋もれてそうです。
幸いにも、ComboBoxのTextChangedで無理矢理値を書き換えることで修正が可能です。
TextChangedイベントは次のXAMLかコードビハインドによって設定できます。
参考:http://stackoverflow.com/questions/6914942/how-do-i-get-textchanged-events-from-an-editable-combobox
<ComboBox IsEditable="True" TextBoxBase.TextChanged="ComboBox_TextChanged" />
public MainWindow() {
InitializeComponent();
comboBox.AddHandler(System.Windows.Controls.Primitives.TextBoxBase.TextChangedEvent,
new System.Windows.Controls.TextChangedEventHandler(ComboBox_TextChanged));
}
ComboBox_TextChangedメソッドは次のように設定します。TextChangedEventArgs.OriginalSourceプロパティはイベントを発生させた大本のElementを取得できるので、ComboBoxのPart_EditableTextBoxを取得できます。
protected virtual void ComboBox_TextChanged(object sender, TextChangedEventArgs e) {
var tb = e.OriginalSource as TextBox;
if (tb != null) {
((ComboBox)sender).Text = tb.Text;
}
}
※2015/11/22追記
Windows10、.NET 4.6環境にしたら普通に変換できました。
やはりWindows8.1が問題だったみたいです。
2015年1月31日土曜日
WPFでIntelliSense
http://challengeandresponse.blogspot.jp/2014/04/wpfctextbox.html
こちらのサイトでWPFでIntelliSenseを使う方法が例示されているが、いくつか不満点があるため何箇所か改良を行いました。
こちらのサイトでWPFでIntelliSenseを使う方法が例示されているが、いくつか不満点があるため何箇所か改良を行いました。
- フィルターでToUpperしていなかったので、すべての要素が正しく表示されない
→ToUpperを挿入した - 表示されている要素の幅次第でポップアップの幅も変わる(次図)
→ItemsPanelTemplateを用いることで解決した
変更後
<Window x:Class="IntelliSenseTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
xmlns:local="clr-namespace:IntelliSenseTest"
Title="MainWindow" Height="300" Width="500">
<Window.DataContext>
<local:ViewModel x:Name="vm"/>
</Window.DataContext>
<Window.Resources>
<Style TargetType="local:IntelliSenseTextBox">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="TextBackground" Value="Ivory" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<TextBox AcceptsReturn="True" AcceptsTab="True" Name="queryTextBox" Margin="5"
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"
PreviewKeyDown="queryTextBox_PreviewKeyDown"/>
<Popup Name="popup" IsOpen="False" StaysOpen="False" MaxHeight="300" FocusVisualStyle="{x:Null}">
<ListBox IsTextSearchEnabled="False" Name="intellisenseListBox"
PreviewKeyDown="intellisenseListBox_PreviewKeyDown"
MouseDoubleClick="intellisenseListBox_MouseDoubleClick"
DisplayMemberPath="Key" SelectedValuePath="Key"
ItemsSource="{Binding}" FocusVisualStyle="{x:Null}"
>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<StackPanel Background="{TemplateBinding Background}">
<TextBlock Text="{Binding Key}" Foreground="{Binding Path=ForeColor}"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Aqua" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="AliceBlue" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Popup>
</Grid>
</Window>
namespace IntelliSenseTest {
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
// 項目設定
var items = typeof(Brushes).GetProperties().Select(brush => new CandidateKeyItem() { Key = brush.Name, ForeColor = (Brush)brush.GetValue(null, null) }).ToList();
intellisenseListBox.DataContext = items;
this.intellisenseView = CollectionViewSource.GetDefaultView(items);
this.intellisenseView.Filter = filterIntellisense;
}
/// <summary>
/// 候補キーアイテム
/// </summary>
public class CandidateKeyItem {
/// <summary>
/// 候補キー
/// </summary>
public string Key { get; set; }
/// <summary>
/// 文字色
/// </summary>
public Brush ForeColor { get; set; }
}
/// <summary>
/// インテリセンスコレクションビュー
/// </summary>
private ICollectionView intellisenseView;
/// <summary>
/// カレント単語
/// </summary>
private string currentWord = "*";
/// <summary>
/// クエリテキストボックスプレビューキーダウンイベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void queryTextBox_PreviewKeyDown(object sender, KeyEventArgs e) {
// インテリセンス
if (e.Key == Key.Back || e.Key == Key.Escape) {
popup.IsOpen = false;
return;
}
if (popup.IsOpen) {
if (e.Key == Key.Tab || e.Key == Key.Down) {
intellisenseListBox.Focus();
return;
}
if (e.Key == Key.Enter && intellisenseListBox.Items.Count != 0) {
if (intellisenseListBox.SelectedIndex == -1) {
intellisenseListBox.SelectedIndex = 0;
}
selectWord();
e.Handled = true;
return;
}
}
// フィルタ対象外判定
int key = (int)e.Key;
if ((key < 34) || (85 < key) && (key < 140) || (154 < key)) {
return;
}
this.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => {
currentWord = getCurrentWord(queryTextBox);
if (string.IsNullOrEmpty(currentWord)) {
popup.IsOpen = false;
return;
}
intellisenseView.Refresh();
// Popupを現在のキャレットのある位置へ表示
popup.PlacementTarget = queryTextBox;
popup.PlacementRectangle =
queryTextBox.GetRectFromCharacterIndex(queryTextBox.CaretIndex);
// 候補が0個の時は表示しない
popup.IsOpen = intellisenseListBox.Items.Count != 0;
if (popup.IsOpen && intellisenseListBox.SelectedItem != null) {
// 既に選択したものがあればそこにスクロール
intellisenseListBox.ScrollIntoView(intellisenseListBox.SelectedItem);
}
}));
}
/// <summary>
/// リストボックスプレビューキーダウンイベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void intellisenseListBox_PreviewKeyDown(object sender, KeyEventArgs e) {
// ESCAPE押下でポップアップキャンセル
if (e.Key == Key.Escape) {
popup.IsOpen = false;
queryTextBox.Focus();
return;
}
// 文字選択判定
if (e.Key == Key.Enter || e.Key == Key.Tab || e.Key == Key.Space) {
selectWord();
e.Handled = true;
}
}
/// <summary>
/// リストビューダブルクリックイベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void intellisenseListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
selectWord();
}
/// <summary>
/// カレント文字取得
/// </summary>
/// <param name="textBox"></param>
/// <returns></returns>
private string getCurrentWord(TextBox textBox) {
if (string.IsNullOrEmpty(textBox.Text)) {
return string.Empty;
}
if (textBox.CaretIndex == 0) {
return string.Empty;
}
int index = textBox.CaretIndex - 1;
int last = textBox.Text.LastIndexOfAny(new[] { ' ', '\r', '\n', '\t' }, index) + 1;
return textBox.Text.Substring(last, textBox.CaretIndex - last).ToUpper();
}
/// <summary>
/// インテリセンスフィルター
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
private bool filterIntellisense(object args) {
bool result = false;
var word = args as CandidateKeyItem;
if (word != null) {
result = word.Key.ToUpper().Contains(currentWord);
}
return result;
}
/// <summary>
/// ワード選択
/// </summary>
private void selectWord() {
if (intellisenseListBox.SelectedValue == null) {
return;
}
var caretIndex = queryTextBox.CaretIndex;
var selectedText = intellisenseListBox.SelectedValue as string;
var topIndex = caretIndex - currentWord.Length;
// 選択されたものを挿入
var tmpText = queryTextBox.Text.Remove(topIndex, currentWord.Length);
queryTextBox.Text = tmpText.Insert(topIndex, selectedText);
queryTextBox.CaretIndex = topIndex + selectedText.Length;
popup.IsOpen = false;
queryTextBox.Focus();
}
}
}
登録:
コメント (Atom)

