1 // OpenTween - Client of Twitter
2 // Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
3 // (c) 2008-2011 Moz (@syo68k)
4 // (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
5 // (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
6 // (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
7 // (c) 2011 Egtra (@egtra) <http://dev.activebasic.com/egtra/>
8 // (c) 2014 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
9 // All rights reserved.
11 // This file is part of OpenTween.
13 // This program is free software; you can redistribute it and/or modify it
14 // under the terms of the GNU General public License as published by the Free
15 // Software Foundation; either version 3 of the License, or (at your option)
18 // This program is distributed in the hope that it will be useful, but
19 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General public License
23 // You should have received a copy of the GNU General public License along
24 // with this program. if not, see <http://www.gnu.org/licenses/>, or write to
25 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
26 // Boston, MA 02110-1301, USA.
29 using System.ComponentModel;
30 using System.Diagnostics;
33 using System.Runtime.InteropServices;
34 using System.Threading;
35 using System.Windows.Forms;
37 using OpenTween.Connection;
41 internal static class NativeMethods
43 // 指定されたウィンドウへ、指定されたメッセージを送信します
44 [DllImport("user32.dll")]
45 private extern static IntPtr SendMessage(
51 [DllImport("user32.dll")]
52 private extern static IntPtr SendMessage(
58 // SendMessageで送信するメッセージ
59 private enum SendMessageType : uint
61 WM_SETREDRAW = 0x000B, //再描画を許可するかを設定
62 WM_USER = 0x400, //ユーザー定義メッセージ
64 TCM_FIRST = 0x1300, //タブコントロールメッセージ
65 TCM_SETMINTABWIDTH = TCM_FIRST + 49, //タブアイテムの最小幅を設定
67 LVM_FIRST = 0x1000, //リストビューメッセージ
68 LVM_SETITEMSTATE = LVM_FIRST + 43, //アイテムの状態を設定
69 LVM_GETSELECTIONMARK = LVM_FIRST + 66, //複数選択時の起点になるアイテムの位置を取得
70 LVM_SETSELECTIONMARK = LVM_FIRST + 67, //複数選択時の起点になるアイテムを設定
74 /// コントロールの再描画を許可するかを設定します
76 /// <param name="control">対象となるコントロール</param>
77 /// <param name="redraw">再描画を許可する場合は true、抑制する場合は false</param>
78 /// <returns>このメッセージを処理する場合、アプリケーションは 0 を返します</returns>
79 public static int SetRedrawState(Control control, bool redraw)
81 var state = redraw ? new IntPtr(1) : IntPtr.Zero;
82 return (int)SendMessage(control.Handle, SendMessageType.WM_SETREDRAW, state, IntPtr.Zero);
86 /// タブコントロールのアイテムの最小幅を設定します
88 /// <param name="tabControl">対象となるタブコントロール</param>
89 /// <param name="width">アイテムの最小幅。-1 を指定するとデフォルトの幅が使用されます</param>
90 /// <returns>設定前の最小幅</returns>
91 public static int SetMinTabWidth(TabControl tabControl, int width)
93 return (int)SendMessage(tabControl.Handle, SendMessageType.TCM_SETMINTABWIDTH, IntPtr.Zero, (IntPtr)width);
96 // 参照: LVITEM structure (Windows)
97 // http://msdn.microsoft.com/en-us/library/windows/desktop/bb774760%28v=vs.85%29.aspx
98 [StructLayout(LayoutKind.Sequential)]
99 [BestFitMapping(false, ThrowOnUnmappableChar = true)]
100 private struct LVITEM
106 public LVIS stateMask;
107 public string pszText;
108 public int cchTextMax;
110 public IntPtr lParam;
113 public uint cColumns;
114 public uint puColumns;
119 // 参照: List-View Item States (Windows)
120 // http://msdn.microsoft.com/en-us/library/windows/desktop/bb774733%28v=vs.85%29.aspx
122 private enum LVIS : uint
128 /// ListView のアイテムを選択された状態にします
130 /// <param name="listView">対象となる ListView</param>
131 /// <param name="index">選択するアイテムのインデックス</param>
132 /// <returns>成功した場合は true、それ以外の場合は false</returns>
133 public static bool SelectItem(ListView listView, int index)
135 // LVM_SETITEMSTATE では stateMask, state 以外のメンバーは無視される
136 var lvitem = new LVITEM
138 stateMask = LVIS.SELECTED,
139 state = LVIS.SELECTED,
142 var ret = (int)SendMessage(listView.Handle, SendMessageType.LVM_SETITEMSTATE, (IntPtr)index, ref lvitem);
147 /// ListView の全アイテムを選択された状態にします
149 /// <param name="listView">対象となる ListView</param>
150 /// <returns>成功した場合は true、それ以外の場合は false</returns>
151 public static bool SelectAllItems(ListView listView)
153 return SelectItem(listView, -1 /* all items */);
157 public static bool FlashMyWindow(IntPtr hwnd,
158 FlashSpecification flashType,
161 var fInfo = new FLASHWINFO();
162 fInfo.cbSize = Convert.ToInt32(Marshal.SizeOf(fInfo));
164 fInfo.dwFlags = (int)FlashSpecification.FlashAll;
165 fInfo.uCount = flashCount;
168 return FlashWindowEx(ref fInfo);
171 public enum FlashSpecification : uint
173 FlashStop = FLASHW_STOP,
174 FlashCaption = FLASHW_CAPTION,
175 FlashTray = FLASHW_TRAY,
176 FlashAll = FLASHW_ALL,
177 FlashTimer = FLASHW_TIMER,
178 FlashTimerNoForeground = FLASHW_TIMERNOFG,
180 /// http://www.atmarkit.co.jp/fdotnet/dotnettips/723flashwindow/flashwindow.html
181 [DllImport("user32.dll")]
182 [return: MarshalAs(UnmanagedType.Bool)]
183 private static extern bool FlashWindowEx(
184 ref FLASHWINFO FWInfo);
187 private struct FLASHWINFO
189 public Int32 cbSize; // FLASHWINFO構造体のサイズ
190 public IntPtr hwnd; // 点滅対象のウィンドウ・ハンドル
191 public Int32 dwFlags; // 以下の「FLASHW_XXX」のいずれか
192 public Int32 uCount; // 点滅する回数
193 public Int32 dwTimeout; // 点滅する間隔(ミリ秒単位)
197 private const Int32 FLASHW_STOP = 0;
199 private const Int32 FLASHW_CAPTION = 0x1;
201 private const Int32 FLASHW_TRAY = 0x2;
202 // タスクバー・ボタンとタイトルバーを点滅させる
203 private const Int32 FLASHW_ALL = 0x3;
204 // FLASHW_STOPが指定されるまでずっと点滅させる
205 private const Int32 FLASHW_TIMER = 0x4;
206 // ウィンドウが最前面に来るまでずっと点滅させる
207 private const Int32 FLASHW_TIMERNOFG = 0xC;
210 [DllImport("user32.dll")]
211 [return: MarshalAs(UnmanagedType.Bool)]
212 public static extern bool ValidateRect(
216 #region "selection mark"
217 // 複数選択時の起点になるアイテム (selection mark) の位置を取得する
218 public static int ListView_GetSelectionMark(IntPtr hwndLV)
220 return SendMessage(hwndLV, SendMessageType.LVM_GETSELECTIONMARK, IntPtr.Zero, IntPtr.Zero).ToInt32();
223 // 複数選択時の起点になるアイテム (selection mark) を設定する
224 public static void ListView_SetSelectionMark(IntPtr hwndLV, int itemIndex)
226 SendMessage(hwndLV, SendMessageType.LVM_SETSELECTIONMARK, IntPtr.Zero, (IntPtr)itemIndex);
230 #region "スクリーンセーバー起動中か判定"
231 [DllImport("user32", CharSet = CharSet.Auto)]
232 [return: MarshalAs(UnmanagedType.Bool)]
233 private static extern bool SystemParametersInfo(
236 [MarshalAs(UnmanagedType.Bool)] ref bool bParam,
238 // returns non-zero value if function succeeds
240 //スクリーンセーバーが起動中かを取得する定数
241 private const int SPI_GETSCREENSAVERRUNNING = 0x0072;
243 public static bool IsScreenSaverRunning()
245 var isRunning = false;
246 SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, ref isRunning, 0);
252 [DllImport("user32")]
253 private static extern int RegisterHotKey(IntPtr hwnd, int id,
254 int fsModifiers, int vk);
255 [DllImport("user32")]
256 private static extern int UnregisterHotKey(IntPtr hwnd, int id);
257 [DllImport("kernel32", CharSet = CharSet.Auto, BestFitMapping = false, ThrowOnUnmappableChar = true)]
258 private static extern ushort GlobalAddAtom([MarshalAs(UnmanagedType.LPTStr)] string lpString);
259 [DllImport("kernel32")]
260 private static extern ushort GlobalDeleteAtom(ushort nAtom);
262 private static int registerCount = 0;
263 // register a global hot key
264 public static int RegisterGlobalHotKey(int hotkeyValue, int modifiers, Form targetForm)
269 // use the GlobalAddAtom API to get a unique ID (as suggested by MSDN docs)
271 var atomName = Thread.CurrentThread.ManagedThreadId.ToString("X8") + targetForm.Name + registerCount;
272 hotkeyID = GlobalAddAtom(atomName);
275 throw new Win32Exception();
278 // register the hotkey, throw if any error
279 if (RegisterHotKey(targetForm.Handle, hotkeyID, modifiers, hotkeyValue) == 0)
281 throw new Win32Exception();
287 // clean up if hotkey registration failed
288 UnregisterGlobalHotKey(hotkeyID, targetForm);
293 // unregister a global hotkey
294 public static void UnregisterGlobalHotKey(ushort hotkeyID, Form targetForm)
298 UnregisterHotKey(targetForm.Handle, hotkeyID);
299 // clean up the atom list
300 GlobalDeleteAtom(hotkeyID);
306 #region "プロセスのProxy設定"
308 [DllImport("wininet.dll", SetLastError = true)]
309 [return: MarshalAs(UnmanagedType.Bool)]
310 private static extern bool InternetSetOption(IntPtr hInternet,
311 InternetOption dwOption,
312 [In] ref InternetProxyInfo lpBuffer,
313 int lpdwBufferLength);
315 private enum InternetOption
322 [StructLayout(LayoutKind.Sequential)]
323 [BestFitMapping(false, ThrowOnUnmappableChar = true)]
324 private struct InternetProxyInfo
326 public InternetOpenType dwAccessType;
328 public string proxyBypass;
331 private enum InternetOpenType
333 //PRECONFIG = 0, // IE setting
334 DIRECT = 1, // Direct
338 private static void RefreshProxySettings(string strProxy)
340 InternetProxyInfo ipi;
342 // Filling in structure
343 if (!string.IsNullOrEmpty(strProxy))
345 ipi = new InternetProxyInfo
347 dwAccessType = InternetOpenType.PROXY,
349 proxyBypass = "local",
352 else if (strProxy == null)
355 var p = WebRequest.GetSystemWebProxy();
356 if (p.IsBypassed(new Uri("http://www.google.com/")))
358 ipi = new InternetProxyInfo
360 dwAccessType = InternetOpenType.DIRECT,
367 ipi = new InternetProxyInfo
369 dwAccessType = InternetOpenType.PROXY,
370 proxy = p.GetProxy(new Uri("http://www.google.com/")).Authority,
371 proxyBypass = "local",
377 ipi = new InternetProxyInfo
379 dwAccessType = InternetOpenType.DIRECT,
385 if (!InternetSetOption(IntPtr.Zero, InternetOption.PROXY, ref ipi, Marshal.SizeOf(ipi)))
386 throw new Win32Exception();
389 public static void SetProxy(ProxyType pType, string host, int port, string username, string password)
400 case ProxyType.Specified:
401 proxy = host + (port > 0 ? ":" + port : "");
404 RefreshProxySettings(proxy);
408 [StructLayout(LayoutKind.Sequential)]
409 private struct SCROLLINFO
412 public ScrollInfoMask fMask;
417 public int nTrackPos;
420 public enum ScrollBarDirection
428 private enum ScrollInfoMask
433 SIF_DISABLENOSCROLL = 0x8,
435 SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS),
438 [DllImport("user32.dll")]
439 private static extern int GetScrollInfo(IntPtr hWnd, ScrollBarDirection fnBar, ref SCROLLINFO lpsi);
441 public static int GetScrollPosition(Control control, ScrollBarDirection direction)
443 var si = new SCROLLINFO
445 cbSize = Marshal.SizeOf<SCROLLINFO>(),
446 fMask = ScrollInfoMask.SIF_POS,
449 if (NativeMethods.GetScrollInfo(control.Handle, direction, ref si) == 0)
450 throw new Win32Exception();
457 [DllImport("user32.dll")]
458 private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint procId);
460 [return: MarshalAs(UnmanagedType.Bool)]
461 private delegate bool EnumWindowCallback(IntPtr hWnd, int lParam);
463 [DllImport("user32")]
464 [return: MarshalAs(UnmanagedType.Bool)]
465 private static extern bool EnumWindows(EnumWindowCallback lpEnumFunc, IntPtr lParam);
467 [DllImport("user32.dll", CharSet = CharSet.Unicode)]
468 private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
470 [DllImport("user32.dll", CharSet = CharSet.Unicode)]
471 private static extern int GetWindowTextLength(IntPtr hWnd);
474 /// 指定したPIDとタイトルを持つウィンドウのウィンドウハンドルを取得します
476 /// <param name="pid">対象ウィンドウのPID</param>
477 /// <param name="searchWindowTitle">対象ウィンドウのタイトル</param>
478 /// <returns>ウィンドウハンドル。検索に失敗した場合は<see cref="IntPtr.Zero"/></returns>
479 public static IntPtr GetWindowHandle(uint pid, string searchWindowTitle)
481 var foundHwnd = IntPtr.Zero;
483 EnumWindows((hWnd, lParam) =>
485 GetWindowThreadProcessId(hWnd, out var procId);
489 int windowTitleLen = GetWindowTextLength(hWnd);
491 if (windowTitleLen > 0)
493 StringBuilder windowTitle = new StringBuilder(windowTitleLen + 1);
494 GetWindowText(hWnd, windowTitle, windowTitle.Capacity);
496 if (windowTitle.ToString().Contains(searchWindowTitle))
512 #region "ウィンドウのアクティブ化"
514 private enum ShowWindowCommands : int
516 /// <summary>最小化・最大化されたウィンドウを元に戻して表示</summary>
520 [DllImport("user32.dll")]
521 [return: MarshalAs(UnmanagedType.Bool)]
522 private static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
524 [DllImport("user32.dll")]
525 [return: MarshalAs(UnmanagedType.Bool)]
526 private static extern bool SetForegroundWindow(IntPtr hWnd);
529 /// 指定したウィンドウをアクティブにします
531 /// <param name="hWnd">アクティブにするウィンドウのウィンドウハンドル</param>
532 public static void SetActiveWindow(IntPtr hWnd)
534 ShowWindow(hWnd, ShowWindowCommands.SW_RESTORE);
535 SetForegroundWindow(hWnd);