-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
250 lines (185 loc) · 75.5 KB
/
atom.xml
File metadata and controls
250 lines (185 loc) · 75.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Easher' Blog</title>
<link href="/atom.xml" rel="self"/>
<link href="https://shalyf.github.io/"/>
<updated>2017-07-16T05:42:12.000Z</updated>
<id>https://shalyf.github.io/</id>
<author>
<name>Easher</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>多张PNG图片合并成一张TIFF</title>
<link href="https://shalyf.github.io/2017/convert-pngs-to-tiff/"/>
<id>https://shalyf.github.io/2017/convert-pngs-to-tiff/</id>
<published>2017-07-15T14:30:04.000Z</published>
<updated>2017-07-16T05:42:12.000Z</updated>
<content type="html"><![CDATA[<p><code>iOS</code>和<code>macOS</code>开发中常用<code>PNG</code>文件作为图片资源,我们常使用<code>imageNamed</code>来使用图片资源,一般大家的做法都是让<code>UI</code>切图的时候给三个文件</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">icon@1x.png</div><div class="line">icon@2x.png</div><div class="line">icon@3x.png</div></pre></td></tr></table></figure>
<p>但是有时候情况特殊,你只能使用一个文件,比如在<code>Apple Script</code>中使用图片,那怎么办呢,经常接触<code>macOS</code>的人应该都见过<code>TIFF</code></p>
<blockquote>
<p>TIFF是一个灵活适应性强的文件格式。通过在文件标头中使用“标签”,它能够在一个文件中处理多幅图像和数据。<br><a href="https://zh.wikipedia.org/wiki/TIFF#.E7.81.B5.E6.B4.BB.E7.9A.84.E9.80.89.E9.A1.B9" target="_blank" rel="external">维基百科</a></p>
</blockquote>
<p>注意,<code>TIFF</code>是支持多页的,可以用一个<code>TIFF</code>文件包含上面的三幅图像,那怎么把三张<code>PNG</code>变成一张<code>TIFF</code>呢?我们有<code>ImageMagick</code>,不想装的可以看最后。</p>
<blockquote>
<p>ImageMagick是一个用于查看、编辑位图文件以及进行图像格式转换的开放源代码软件套装。它可以读取、编辑超过100种图象格式。<br>ImageMagick最基本的一个功能是准确高效地转换超过68种图片的格式,包括众所周知的TIFF、JPEG、PNG、PDF、PhotoCD,以及GIF。<br><a href="https://zh.wikipedia.org/wiki/ImageMagick#.E6.96.87.E4.BB.B6.E6.A0.BC.E5.BC.8F.E8.BD.AC.E6.8D.A2" target="_blank" rel="external">维基百科</a></p>
</blockquote>
<p><code>ImageMagick</code>可以用<a href="https://brew.sh" target="_blank" rel="external">HomeBrew</a>快速安装</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ brew install imagemagick</div></pre></td></tr></table></figure>
<p><code>convert</code>是<code>ImageMagick</code>用于转换图片格式的工具</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ convert icon@1x.png icon@2x.png icon@3x.png icon.tiff</div></pre></td></tr></table></figure>
<p>现在我们获得了<code>icon.tiff</code>这个文件,用自带的预览工具打开即可看到它包含了三幅图像,目标达成!</p>
<hr>
<p>但是我连<code>HomeBrew</code>都没装,太麻烦了啦,有没有更简单的,答案是有。</p>
<p><code>tiffutil</code>是<code>macOS</code>自带的用于操作<code>TIFF</code>文件的工具,它在<code>macOS 10.9</code>之后被内置在<code>usr/bin/</code>中,另外还有配套其他一些工具用来操作<code>TIFF</code>,比如<code>tiffinfo</code>等等。</p>
<p>用法其实也很简单:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ tiffutil -cathidpicheck icon@1x.png icon@2x.png icon@3x.png -out icon.tiff</div></pre></td></tr></table></figure>
<p>具体用法可以查看<a href="https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/tiffutil.1.html" target="_blank" rel="external">官方文档</a></p>
]]></content>
<summary type="html">
<p><code>iOS</code>和<code>macOS</code>开发中常用<code>PNG</code>文件作为图片资源,我们常使用<code>imageNamed</code>来使用图片资源,一般大家的做法都是让<code>UI</code>切图的时候给三个文件<
</summary>
<category term="Apple" scheme="https://shalyf.github.io/categories/Apple/"/>
<category term="macOS" scheme="https://shalyf.github.io/tags/macOS/"/>
</entry>
<entry>
<title>鼠标事件响应</title>
<link href="https://shalyf.github.io/2016/mouse-event/"/>
<id>https://shalyf.github.io/2016/mouse-event/</id>
<published>2016-02-01T05:21:09.000Z</published>
<updated>2017-07-15T15:43:37.000Z</updated>
<content type="html"><![CDATA[<p><code>NSResponder</code>提供了鼠标响应事件,而所有的视图都继承自<code>NSResponder</code>,所以我们可以很方便的处理鼠标事件。</p>
<h2 id="鼠标一般事件"><a href="#鼠标一般事件" class="headerlink" title="鼠标一般事件"></a>鼠标一般事件</h2><p>鼠标一般事件有按下和松开,又有左右键和其它键之分(本文只讨论左右键),对应的消息如下:</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 按下鼠标左键</span></div><div class="line">- (<span class="keyword">void</span>)mouseDown:(<span class="built_in">NSEvent</span> *)theEvent;</div><div class="line"><span class="comment">// 松开鼠标左键</span></div><div class="line">- (<span class="keyword">void</span>)mouseUp:(<span class="built_in">NSEvent</span> *)theEvent;</div><div class="line"><span class="comment">// 按下鼠标右键</span></div><div class="line">- (<span class="keyword">void</span>)rightMouseDown:(<span class="built_in">NSEvent</span> *)theEvent;</div><div class="line"><span class="comment">// 松开鼠标右键</span></div><div class="line">- (<span class="keyword">void</span>)rightMouseUp:(<span class="built_in">NSEvent</span> *)theEvent;</div></pre></td></tr></table></figure>
<p>鼠标点击后,<code>NSEvent</code>捕获到的坐标是基于<code>Window</code>的,所以需要经过转换才能使用。</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">- (<span class="keyword">void</span>)mouseDown:(<span class="built_in">NSEvent</span> *)theEvent {</div><div class="line"> <span class="comment">/**</span></div><div class="line"> * 将mouseDown消息传递给父类</div><div class="line"> * 注意,如果写了这句的话,mouseUp事件将不会触发</div><div class="line"> */</div><div class="line"> [<span class="keyword">super</span> mouseDown:theEvent];</div><div class="line"></div><div class="line"> <span class="comment">// 将鼠标点击位置的坐标从Window转换为当前View,fromView设为nil表示从Window转换</span></div><div class="line"> <span class="built_in">NSPoint</span> location = [<span class="keyword">self</span> convertPoint:theEvent.locationInWindow fromView:<span class="literal">nil</span>];</div><div class="line"> </div><div class="line"> <span class="comment">// doing something</span></div><div class="line">}</div></pre></td></tr></table></figure>
<a id="more"></a>
<h2 id="鼠标跟踪事件"><a href="#鼠标跟踪事件" class="headerlink" title="鼠标跟踪事件"></a>鼠标跟踪事件</h2><p>鼠标跟踪是通过定义一个矩形区域,捕获在这个区域内鼠标的进出和移动事件。这个监视区可以在<code>awakeFromNib</code>中用<code>addTrackingArea:</code>方法注册。</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">- (<span class="keyword">void</span>)awakeFromNib {</div><div class="line"> <span class="comment">// 创建监视区</span></div><div class="line"> <span class="built_in">NSTrackingArea</span> *trackingArea = [[<span class="built_in">NSTrackingArea</span> alloc] initWithRect:<span class="keyword">self</span>.bounds options:</div><div class="line"> <span class="built_in">NSTrackingMouseMoved</span> |</div><div class="line"> <span class="built_in">NSTrackingMouseEnteredAndExited</span> |</div><div class="line"> <span class="built_in">NSTrackingActiveAlways</span> owner:<span class="keyword">self</span> userInfo:<span class="literal">nil</span>];</div><div class="line"> </div><div class="line"> <span class="comment">// 添加到View中</span></div><div class="line"> [<span class="keyword">self</span> addTrackingArea:trackingArea];</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">// 鼠标进入监视区</span></div><div class="line">- (<span class="keyword">void</span>)mouseEntered:(<span class="built_in">NSEvent</span> *)theEvent;</div><div class="line"><span class="comment">// 鼠标在监视区内移动</span></div><div class="line">- (<span class="keyword">void</span>)mouseMoved:(<span class="built_in">NSEvent</span> *)theEvent</div><div class="line"><span class="comment">// 鼠标推出监视区</span></div><div class="line">- (<span class="keyword">void</span>)mouseExited:(<span class="built_in">NSEvent</span> *)theEvent;</div></pre></td></tr></table></figure>
<p>上述代码定义了一个<code>self.bounds</code>的矩形区域,在这个区域内的鼠标事件将被捕获。然而很多时候<code>View</code>的<code>frame</code>和<code>bounds</code>是会变化的,变化后在<code>awakeFromNib</code>中注册的监视区就与<code>View</code>不重合了,就会出现事件不会触发或者坐标偏差等现象。这个问题,可以通过重写<code>updateTrackingAreas</code>方法重新创建监视区来解决,<code>updateTrackingAreas</code>在控件大小或者坐标发生变化的时候会被触发。</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 定义一个变量来存储监视区</span></div><div class="line"><span class="built_in">NSTrackingArea</span> *_trackingArea;</div><div class="line"></div><div class="line">- (<span class="keyword">void</span>)updateTrackingAreas {</div><div class="line"> [<span class="keyword">super</span> updateTrackingAreas];</div><div class="line"> </div><div class="line"> <span class="keyword">if</span> (_trackingArea) <span class="comment">// 移除久的监视区</span></div><div class="line"> [<span class="keyword">self</span> removeTrackingArea:_trackingArea];</div><div class="line"> </div><div class="line"> <span class="comment">// 创建新的监视区</span></div><div class="line"> _trackingArea = [[<span class="built_in">NSTrackingArea</span> alloc] initWithRect:<span class="keyword">self</span>.bounds options:</div><div class="line"> <span class="built_in">NSTrackingMouseMoved</span> |</div><div class="line"> <span class="built_in">NSTrackingMouseEnteredAndExited</span> |</div><div class="line"> <span class="built_in">NSTrackingActiveAlways</span> owner:<span class="keyword">self</span> userInfo:<span class="literal">nil</span>];</div><div class="line"> </div><div class="line"> <span class="comment">// 添加到View中</span></div><div class="line"> [<span class="keyword">self</span> addTrackingArea:_trackingArea];</div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="鼠标拖拽事件"><a href="#鼠标拖拽事件" class="headerlink" title="鼠标拖拽事件"></a>鼠标拖拽事件</h2><p>鼠标拖拽顾名思义就是鼠标按下后不松开,然后移动鼠标,到目标位置后才松开,这三步完成了一次完整的鼠标拖拽动作。</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 鼠标左键拖拽</span></div><div class="line">- (<span class="keyword">void</span>)mouseDragged:(<span class="built_in">NSEvent</span> *)theEvent;</div><div class="line"><span class="comment">// 鼠标右键拖拽</span></div><div class="line">- (<span class="keyword">void</span>)rightMouseDragged:(<span class="built_in">NSEvent</span> *)theEvent;</div></pre></td></tr></table></figure>
<p>一次完整的拖拽动作代码是这样的:</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">BOOL</span> isDragged = <span class="literal">NO</span>;</div><div class="line"></div><div class="line">- (<span class="keyword">void</span>)mouseDown:(<span class="built_in">NSEvent</span> *)theEvent {</div><div class="line"> <span class="comment">// 鼠标按下,开始拖拽</span></div><div class="line"> isDragged = <span class="literal">YES</span>;</div><div class="line">}</div><div class="line"></div><div class="line">- (<span class="keyword">void</span>)mouseDragged:(<span class="built_in">NSEvent</span> *)theEvent {</div><div class="line"> </div><div class="line"> <span class="keyword">if</span> (isDragged) { <span class="comment">// 拖拽中</span></div><div class="line"> </div><div class="line"> <span class="comment">// 这里不转换坐标的原因是setFrameOrigin需要用的就是在Window中的坐标</span></div><div class="line"> <span class="built_in">NSPoint</span> location = theEvent.locationInWindow;</div><div class="line"> </div><div class="line"> <span class="comment">// 改变控件在Window中的位置,当然这只是简单的写法,效果并不是特别好</span></div><div class="line"> [<span class="keyword">self</span> setFrameOrigin:location];</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line">- (<span class="keyword">void</span>)mouseUp:(<span class="built_in">NSEvent</span> *)theEvent {</div><div class="line"> <span class="comment">// 鼠标松开,结束拖拽</span></div><div class="line"> isDragged = <span class="literal">NO</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<p>上面的代码需要三个方法来解决一个问题,还需要外部状态码来控制,有没有更优雅的写法呢?查阅<a href="https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/EventOverview/HandlingMouseEvents/HandlingMouseEvents.html#//apple_ref/doc/uid/10000060i-CH6-SW4" target="_blank" rel="external">苹果文档</a>,发现可以在<code>mouseDown</code>里面循环监听需要的鼠标事件。</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div></pre></td><td class="code"><pre><div class="line">- (<span class="keyword">void</span>)mouseDown:(<span class="built_in">NSEvent</span> *)theEvent {</div><div class="line"></div><div class="line"> <span class="built_in">BOOL</span> keepOn = <span class="literal">YES</span>;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (keepOn) {</div><div class="line"> theEvent = [<span class="keyword">self</span>.window nextEventMatchingMask:<span class="built_in">NSLeftMouseUpMask</span> | <span class="built_in">NSLeftMouseDraggedMask</span>];</div><div class="line"> <span class="built_in">NSPoint</span> location = [<span class="keyword">self</span> convertPoint:theEvent.locationInWindow fromView:<span class="literal">nil</span>];</div><div class="line"> <span class="built_in">BOOL</span> isInside = [<span class="keyword">self</span> mouse:location inRect:<span class="keyword">self</span>.bounds];</div><div class="line"> </div><div class="line"> <span class="keyword">switch</span> (theEvent.type) {</div><div class="line"> <span class="keyword">case</span> <span class="built_in">NSLeftMouseUp</span>:</div><div class="line"> keepOn = <span class="literal">NO</span>;</div><div class="line"> </div><div class="line"> <span class="comment">// doing something</span></div><div class="line"> </div><div class="line"> <span class="keyword">if</span> (isInside)</div><div class="line"> [<span class="keyword">super</span> mouseDown:theEvent];</div><div class="line"></div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> </div><div class="line"> <span class="keyword">case</span> <span class="built_in">NSLeftMouseDragged</span>:</div><div class="line"> <span class="comment">// doing something</span></div><div class="line"> <span class="keyword">break</span>;</div><div class="line"></div><div class="line"> <span class="keyword">default</span>:</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<p><code>while</code>创建了一个事件监听循环,通过<code>[NSWindow nextEventMatchingMask:]</code>来监听接下来的<code>NSLeftMouseUpMask</code>(左键抬起)和<code>NSLeftMouseDraggedMask</code>(左键拖动),在<code>theEvent.type == NSLeftMouseUp</code>的时候将<code>keepOn</code>设置为<code>NO</code>以退出循环结束监听。</p>
<blockquote>
<p>注意:使用该方式需要谨慎,尤其是在多个<code>NSView</code>嵌套的时候,容易造成事件混乱。</p>
</blockquote>
]]></content>
<summary type="html">
<p><code>NSResponder</code>提供了鼠标响应事件,而所有的视图都继承自<code>NSResponder</code>,所以我们可以很方便的处理鼠标事件。</p>
<h2 id="鼠标一般事件"><a href="#鼠标一般事件" class="headerlink" title="鼠标一般事件"></a>鼠标一般事件</h2><p>鼠标一般事件有按下和松开,又有左右键和其它键之分(本文只讨论左右键),对应的消息如下:</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 按下鼠标左键</span></div><div class="line">- (<span class="keyword">void</span>)mouseDown:(<span class="built_in">NSEvent</span> *)theEvent;</div><div class="line"><span class="comment">// 松开鼠标左键</span></div><div class="line">- (<span class="keyword">void</span>)mouseUp:(<span class="built_in">NSEvent</span> *)theEvent;</div><div class="line"><span class="comment">// 按下鼠标右键</span></div><div class="line">- (<span class="keyword">void</span>)rightMouseDown:(<span class="built_in">NSEvent</span> *)theEvent;</div><div class="line"><span class="comment">// 松开鼠标右键</span></div><div class="line">- (<span class="keyword">void</span>)rightMouseUp:(<span class="built_in">NSEvent</span> *)theEvent;</div></pre></td></tr></table></figure>
<p>鼠标点击后,<code>NSEvent</code>捕获到的坐标是基于<code>Window</code>的,所以需要经过转换才能使用。</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">- (<span class="keyword">void</span>)mouseDown:(<span class="built_in">NSEvent</span> *)theEvent &#123;</div><div class="line"> <span class="comment">/**</span></div><div class="line"> * 将mouseDown消息传递给父类</div><div class="line"> * 注意,如果写了这句的话,mouseUp事件将不会触发</div><div class="line"> */</div><div class="line"> [<span class="keyword">super</span> mouseDown:theEvent];</div><div class="line"></div><div class="line"> <span class="comment">// 将鼠标点击位置的坐标从Window转换为当前View,fromView设为nil表示从Window转换</span></div><div class="line"> <span class="built_in">NSPoint</span> location = [<span class="keyword">self</span> convertPoint:theEvent.locationInWindow fromView:<span class="literal">nil</span>];</div><div class="line"> </div><div class="line"> <span class="comment">// doing something</span></div><div class="line">&#125;</div></pre></td></tr></table></figure>
</summary>
<category term="Apple" scheme="https://shalyf.github.io/categories/Apple/"/>
<category term="macOS" scheme="https://shalyf.github.io/tags/macOS/"/>
<category term="objc" scheme="https://shalyf.github.io/tags/objc/"/>
</entry>
<entry>
<title>NSWindow.setFrame的坑</title>
<link href="https://shalyf.github.io/2016/nswindow-setframe/"/>
<id>https://shalyf.github.io/2016/nswindow-setframe/</id>
<published>2016-01-25T08:32:05.000Z</published>
<updated>2017-07-15T15:06:34.000Z</updated>
<content type="html"><![CDATA[<p>在<code>macOS</code>的开发中,我们一般使用<code>NSWindow</code>的<code>setFrame</code>来改变窗体的坐标和大小,而坐标和大小一般是靠动态计算得出,这里要讲讲<code>setFrame</code>的一些坑。</p>
<p>我们知道<code>NSRect</code>里的<code>origin</code>和<code>size</code>都是浮点型的,而像素点是整数的,没有说<code>0.5</code>个像素的,真要有<code>0.5</code>像素,在屏幕上的表现要么是<code>0</code>,要么就是<code>1</code>。下面我们来做个小实验:</p>
<p>我们先创建一个<code>window</code><br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">_window = [[<span class="built_in">NSWindow</span> alloc] initWithContentRect:<span class="built_in">NSMakeRect</span>(<span class="number">450</span>, <span class="number">250</span>, <span class="number">400</span>, <span class="number">300</span>) styleMask:<span class="built_in">NSTitledWindowMask</span> | <span class="built_in">NSClosableWindowMask</span> backing:<span class="built_in">NSBackingStoreBuffered</span> defer:<span class="literal">YES</span>];</div><div class="line">[_window makeKeyAndOrderFront:<span class="keyword">self</span>];</div><div class="line">LogRect(<span class="string">@"window.frame"</span>, _window.frame);</div></pre></td></tr></table></figure></p>
<p>输出如下:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">window.frame: {450.00,250.00,400.00,322.00}</div></pre></td></tr></table></figure></p>
<p>可以看到,除了高度之外,其它值都按照我们提供的参数执行,至于高度为什么多了<code>22</code>,是因为我们设置了<code>NSTitledWindowMask</code>这个<code>styleMask</code>,窗体需要标题栏,高度为<code>22</code>。</p>
<p>接着通过<code>setFrame</code>来改变<code>window</code>的大小<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">[_window setFrame:<span class="built_in">NSMakeRect</span>(<span class="number">450</span>, <span class="number">250</span>, <span class="number">400.5</span>, <span class="number">300</span>) display:<span class="literal">YES</span>];</div><div class="line">LogRect(<span class="string">@"window.changeSize"</span>, _window.frame);</div></pre></td></tr></table></figure></p>
<p>输出如下:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">window.changeSize: {450.00,250.00,401.00,300.00}</div></pre></td></tr></table></figure></p>
<p>可以看到<code>400.5</code>被改成了<code>401</code>,难道<code>NSWindow</code>会把提供的值四舍五入吗?通过实验发现,<code>400.1</code>被改成<code>400</code>,而<code>400.2</code>被改成<code>401</code>,由此看来并非四舍五入,具体实现这边不讨论。所以我们在使用<code>setFrame</code>的时候需要注意提供的参数最后会不会得到我们想要的结果。</p>
<p>说完了大小,我们来看看坐标,这回我们通过<code>setFrame</code>来改变<code>window</code>的坐标。<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">[_window setFrame:<span class="built_in">NSMakeRect</span>(<span class="number">450</span>, <span class="number">250.5</span>, <span class="number">400</span>, <span class="number">300</span>) display:<span class="literal">YES</span>];</div><div class="line">LogRect(<span class="string">@"window.changeOrigin"</span>, _window.frame);</div></pre></td></tr></table></figure></p>
<p>通过前面的结果,我们想当然的认为结果应该是 <code>(450,251,400,300)</code>。然而事实并非如此,我们看看输出:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">window.changeOrigin: {450.00,250.00,400.00,301.00}</div></pre></td></tr></table></figure></p>
<p>相当的意外,坐标没变,而高度却加了<code>1</code>,我们没有改高度的啊。百思不得其解,尝试其它<code>y</code>值看看,然后发现<code>250.9</code>的结果是<code>(450,251,400,300)</code>,<code>250.8</code>的结果是<code>(450,250,400,301)</code>。惊呆了有木有,在此只能劝大家动态计算的时候最好把浮点型转换成整形再传递给<code>setFrame</code>。如果有人知道这是为什么,烦请告知,谢谢!</p>
]]></content>
<summary type="html">
<p>在<code>macOS</code>的开发中,我们一般使用<code>NSWindow</code>的<code>setFrame</code>来改变窗体的坐标和大小,而坐标和大小一般是靠动态计算得出,这里要讲讲<code>setFrame</code>的一些坑。</p>
</summary>
<category term="Apple" scheme="https://shalyf.github.io/categories/Apple/"/>
<category term="macOS" scheme="https://shalyf.github.io/tags/macOS/"/>
<category term="objc" scheme="https://shalyf.github.io/tags/objc/"/>
</entry>
<entry>
<title>让自定义view铺满整个NSWindow</title>
<link href="https://shalyf.github.io/2016/nswindow-full-size-content-view/"/>
<id>https://shalyf.github.io/2016/nswindow-full-size-content-view/</id>
<published>2016-01-23T06:11:20.000Z</published>
<updated>2017-07-15T15:06:29.000Z</updated>
<content type="html"><![CDATA[<h1 id="让自定义view铺满整个NSWindow"><a href="#让自定义view铺满整个NSWindow" class="headerlink" title="让自定义view铺满整个NSWindow"></a>让自定义view铺满整个NSWindow</h1><p>我们通过<code>IB</code>拖到窗体中的控件都是放到<code>NSWindow</code>的<code>contentView</code>视图中的,但是这个<code>contentView</code>不是铺满整个<code>window</code>的,顶部会有一个系统风格的<code>titlebarView</code>,现在项目需要让自定义的<code>view</code>可以铺满整个<code>window</code>。<br>在<code>macOS 10.10</code>之前,我们可以通过简单的两行代码来搞定:</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//把自定义的view添加到contentView的superview中,也就是NSThemeView</span></div><div class="line"><span class="built_in">NSView</span> *themeView = [window.contentView superview];</div><div class="line">[themeView addSubview:<span class="keyword">self</span>.viewCustom positioned:<span class="built_in">NSWindowBelow</span> relativeTo:<span class="literal">nil</span>];</div></pre></td></tr></table></figure>
<p>但是在<code>macOS 10.10</code>以后,运行以上代码,会得到一段警告:</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">NSWindow</span> warning: adding an unknown subview: <<span class="built_in">NSView</span>: <span class="number">0x608000120fa0</span>>. Break on <span class="built_in">NSLog</span> to debug.</div></pre></td></tr></table></figure>
<p>虽然目前并不会影响程序的执行,但是对于有点洁癖的人来说,看到这段警告还是很不爽的,那么在Yosemite我们要怎么避免这个错误而实现我们的目的呢?</p>
<p><code>macOS 10.10</code>之后,<code>NSWindow</code>的<code>styleMask</code>新增了一个<br><code>NSFullSizeContentViewWindowMask</code>,可以通过<code>NSWindow</code>的<code>setStyleMask:</code>来设置,也可以直接在IB中勾选<code>Full Size Content View</code>选项。设置完后<code>contentView</code>就会铺满整个窗体,包括<code>titleBar</code>部分。一个设置就搞定了,更方便更实用。</p>
]]></content>
<summary type="html">
<h1 id="让自定义view铺满整个NSWindow"><a href="#让自定义view铺满整个NSWindow" class="headerlink" title="让自定义view铺满整个NSWindow"></a>让自定义view铺满整个NSWindow</h1><
</summary>
<category term="Apple" scheme="https://shalyf.github.io/categories/Apple/"/>
<category term="macOS" scheme="https://shalyf.github.io/tags/macOS/"/>
<category term="objc" scheme="https://shalyf.github.io/tags/objc/"/>
</entry>
<entry>
<title>NSTableView 和 NSOutlineView 修改选中高亮颜色</title>
<link href="https://shalyf.github.io/2015/nstableview-highlight-selected-color/"/>
<id>https://shalyf.github.io/2015/nstableview-highlight-selected-color/</id>
<published>2015-11-14T09:14:21.000Z</published>
<updated>2017-07-15T15:06:24.000Z</updated>
<content type="html"><![CDATA[<p><code>NSTableView</code>和<code>NSOutlineView</code>的显示方式有两种,分别是<code>Cell Based</code>和<code>View Based</code>。前者需要重绘<code>Cell</code>来实现高度自定义;后者可以直接添加控件到<code>View</code>中,用起来比较简单,所以也比较常用。</p>
<h2 id="Cell-Based"><a href="#Cell-Based" class="headerlink" title="Cell Based"></a>Cell Based</h2><h3 id="覆写NSTableView或着NSOutlineView中的HighlightSelection方法"><a href="#覆写NSTableView或着NSOutlineView中的HighlightSelection方法" class="headerlink" title="覆写NSTableView或着NSOutlineView中的HighlightSelection方法"></a>覆写NSTableView或着NSOutlineView中的HighlightSelection方法</h3><figure class="highlight cs"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> ovrride <span class="keyword">void</span> <span class="title">HighlightSelection</span> (<span class="params">RectangleF clipRect</span>)</span></div><div class="line">{</div><div class="line"> NSRange aVisibleRowIndexs = <span class="keyword">this</span>.RowsInRect (clipRect);</div><div class="line"> </div><div class="line"> NSIndexSet aSelectRowIndexs = <span class="keyword">this</span>.SelectedRows;</div><div class="line"> <span class="keyword">int</span> aRow = aVisibleRowIndexs.Location;</div><div class="line"> <span class="keyword">int</span> aEndRow = aRow + aVisibleRowIndexs.Length;</div><div class="line"> </div><div class="line"> <span class="comment">// 控制是否获得焦点的颜色</span></div><div class="line"> <span class="comment">// NSGradient gradient;</span></div><div class="line"> <span class="comment">// if (this == this.Window.FirstResponder && this.Window.IsMainWindow && this.Window.IsKeyWindow) {</span></div><div class="line"> <span class="comment">// gradient = new NSGradient (new NSColor[] { TBTheme.ThemeColorWithAlpha (0.5f) });</span></div><div class="line"> <span class="comment">// } else {</span></div><div class="line"> <span class="comment">// gradient = new NSGradient (new NSColor[] { TBTheme.ThemeColorWithAlpha (0.8f) });</span></div><div class="line"> <span class="comment">// }</span></div><div class="line"> </div><div class="line"> <span class="keyword">for</span> (; arow < aEndRow; aRow++) {</div><div class="line"> <span class="keyword">if</span> (aSelectRowIndexs.Contains ((<span class="keyword">uint</span>)aRow)) {</div><div class="line"> RectangleF aRowRect = <span class="keyword">this</span>.RectForRow (aRow);</div><div class="line"> TBTheme.LightThemeColor.Set ();</div><div class="line"> NSGraphics.RectFill (aRowRect);</div><div class="line"> }</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="覆写NSTextFieldCell中的HighlightColor方法"><a href="#覆写NSTextFieldCell中的HighlightColor方法" class="headerlink" title="覆写NSTextFieldCell中的HighlightColor方法"></a>覆写NSTextFieldCell中的HighlightColor方法</h3><figure class="highlight cs"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> ovrride NSColor <span class="title">HighlightColor</span> (<span class="params">RectangleF cellFrame, NSView controlView</span>)</span></div><div class="line">{</div><div class="line"> <span class="keyword">return</span> TBTheme.LightThemeColor;</div><div class="line">}</div></pre></td></tr></table></figure>
<a id="more"></a>
<h2 id="View-Based"><a href="#View-Based" class="headerlink" title="View Based"></a>View Based</h2><h3 id="覆写NSTableRowView中的DrawBackground方法"><a href="#覆写NSTableRowView中的DrawBackground方法" class="headerlink" title="覆写NSTableRowView中的DrawBackground方法"></a>覆写NSTableRowView中的DrawBackground方法</h3><figure class="highlight cs"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> ovrride <span class="keyword">void</span> <span class="title">DrawBackground</span> (<span class="params">RectangleF dirtyRect</span>)</span></div><div class="line">{</div><div class="line"> <span class="keyword">base</span>.DrawBackground (dirtyRect);</div><div class="line"> </div><div class="line"> <span class="keyword">using</span> (NSBezierPath path = NSBezierPath.FromRect (dirtyRect)) {</div><div class="line"> NSColor backgroundColor = TBTheme.ThemeColorWithAlpha (<span class="number">0.5</span>f);</div><div class="line"> NSIndexSet indexSet = <span class="keyword">new</span> NSIndexSet ();</div><div class="line"> <span class="keyword">int</span> row = <span class="number">-1</span>;</div><div class="line"> </div><div class="line"> <span class="comment">// get indexSet and row</span></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">this</span>.Superview.GetType () == <span class="keyword">typeof</span>(TBTableView)) {</div><div class="line"> indexSet = (<span class="keyword">this</span>.Superview <span class="keyword">as</span> TBTableView).SelectedRows;</div><div class="line"> row = (<span class="keyword">this</span>.Superview <span class="keyword">as</span> TBTableView).RowForView (<span class="keyword">this</span>);</div><div class="line"> }</div><div class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">this</span>.Superview.GetType () == <span class="keyword">typeof</span> (TBOutlineViewEx)) {</div><div class="line"> indexSet = (<span class="keyword">this</span>.Superview <span class="keyword">as</span> TBOutlineViewEx).SelectedRows;</div><div class="line"> row = (<span class="keyword">this</span>.Superview <span class="keyword">as</span> TBOutlineViewEx).RowForView (<span class="keyword">this</span>);</div><div class="line"> }</div><div class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">this</span>.Superview.GetType () == <span class="keyword">typeof</span> (TBOutlineView)) {</div><div class="line"> indexSet = (<span class="keyword">this</span>.Superview <span class="keyword">as</span> TBOutlineView).SelectedRows;</div><div class="line"> row = (<span class="keyword">this</span>.Superview <span class="keyword">as</span> TBOutlineView).RowForView (<span class="keyword">this</span>);</div><div class="line"> backgroundColor = TBTheme.ThemeColor;</div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="comment">// fill color</span></div><div class="line"> <span class="keyword">if</span> (indexse.Contains ((<span class="keyword">uint</span>)row)) {</div><div class="line"> backgroundColor.Set ();</div><div class="line"> path.Fill ();</div><div class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">this</span>.IsHovered) {</div><div class="line"> TBTheme.ThemeColorWithAlpha (<span class="number">0.2</span>f).Set ();</div><div class="line"> path.Fill ();</div><div class="line"> }</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="如果NSTableView或着NSOutlineView中的SelectionHighlightStyle没有设置为None,那么还需要覆写DrawSelection方法"><a href="#如果NSTableView或着NSOutlineView中的SelectionHighlightStyle没有设置为None,那么还需要覆写DrawSelection方法" class="headerlink" title="如果NSTableView或着NSOutlineView中的SelectionHighlightStyle没有设置为None,那么还需要覆写DrawSelection方法"></a>如果NSTableView或着NSOutlineView中的SelectionHighlightStyle没有设置为None,那么还需要覆写DrawSelection方法</h3><figure class="highlight cs"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> ovrride <span class="keyword">void</span> <span class="title">DrawSelection</span> (<span class="params">RectangleF dirtyRect</span>)</span></div><div class="line">{</div><div class="line"> <span class="comment">// base.DrawSelection (dirtyRect);</span></div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="覆写Delegate中的RowViewForItem方法"><a href="#覆写Delegate中的RowViewForItem方法" class="headerlink" title="覆写Delegate中的RowViewForItem方法"></a>覆写Delegate中的RowViewForItem方法</h3><figure class="highlight cs"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> ovrride NSTableRowView <span class="title">RowViewForItem</span> (<span class="params">NSOutlineView outlineView, NSObject item</span>)</span></div><div class="line">{</div><div class="line"> <span class="keyword">string</span> identity = item.Handle.ToString ();</div><div class="line"> NSView view = outlineView.MakeView (identity, <span class="keyword">this</span>);</div><div class="line"> <span class="keyword">if</span> (view == <span class="literal">null</span>) {</div><div class="line"> TBTableRowView rowView = <span class="keyword">new</span> TBTableRowView ();</div><div class="line"> rowView.Identifier = identity;</div><div class="line"> view = rowView;</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> view <span class="keyword">as</span> TBTableRowView;</div><div class="line">}</div></pre></td></tr></table></figure>
]]></content>
<summary type="html">
<p><code>NSTableView</code>和<code>NSOutlineView</code>的显示方式有两种,分别是<code>Cell Based</code>和<code>View Based</code>。前者需要重绘<code>Cell</code>来实现高度自定义;后者可以直接添加控件到<code>View</code>中,用起来比较简单,所以也比较常用。</p>
<h2 id="Cell-Based"><a href="#Cell-Based" class="headerlink" title="Cell Based"></a>Cell Based</h2><h3 id="覆写NSTableView或着NSOutlineView中的HighlightSelection方法"><a href="#覆写NSTableView或着NSOutlineView中的HighlightSelection方法" class="headerlink" title="覆写NSTableView或着NSOutlineView中的HighlightSelection方法"></a>覆写NSTableView或着NSOutlineView中的HighlightSelection方法</h3><figure class="highlight cs"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> ovrride <span class="keyword">void</span> <span class="title">HighlightSelection</span> (<span class="params">RectangleF clipRect</span>)</span></div><div class="line">&#123;</div><div class="line"> NSRange aVisibleRowIndexs = <span class="keyword">this</span>.RowsInRect (clipRect);</div><div class="line"> </div><div class="line"> NSIndexSet aSelectRowIndexs = <span class="keyword">this</span>.SelectedRows;</div><div class="line"> <span class="keyword">int</span> aRow = aVisibleRowIndexs.Location;</div><div class="line"> <span class="keyword">int</span> aEndRow = aRow + aVisibleRowIndexs.Length;</div><div class="line"> </div><div class="line"> <span class="comment">// 控制是否获得焦点的颜色</span></div><div class="line"> <span class="comment">// NSGradient gradient;</span></div><div class="line"> <span class="comment">// if (this == this.Window.FirstResponder &amp;&amp; this.Window.IsMainWindow &amp;&amp; this.Window.IsKeyWindow) &#123;</span></div><div class="line"> <span class="comment">// gradient = new NSGradient (new NSColor[] &#123; TBTheme.ThemeColorWithAlpha (0.5f) &#125;);</span></div><div class="line"> <span class="comment">// &#125; else &#123;</span></div><div class="line"> <span class="comment">// gradient = new NSGradient (new NSColor[] &#123; TBTheme.ThemeColorWithAlpha (0.8f) &#125;);</span></div><div class="line"> <span class="comment">// &#125;</span></div><div class="line"> </div><div class="line"> <span class="keyword">for</span> (; arow &lt; aEndRow; aRow++) &#123;</div><div class="line"> <span class="keyword">if</span> (aSelectRowIndexs.Contains ((<span class="keyword">uint</span>)aRow)) &#123;</div><div class="line"> RectangleF aRowRect = <span class="keyword">this</span>.RectForRow (aRow);</div><div class="line"> TBTheme.LightThemeColor.Set ();</div><div class="line"> NSGraphics.RectFill (aRowRect);</div><div class="line"> &#125;</div><div class="line"> &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<h3 id="覆写NSTextFieldCell中的HighlightColor方法"><a href="#覆写NSTextFieldCell中的HighlightColor方法" class="headerlink" title="覆写NSTextFieldCell中的HighlightColor方法"></a>覆写NSTextFieldCell中的HighlightColor方法</h3><figure class="highlight cs"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> ovrride NSColor <span class="title">HighlightColor</span> (<span class="params">RectangleF cellFrame, NSView controlView</span>)</span></div><div class="line">&#123;</div><div class="line"> <span class="keyword">return</span> TBTheme.LightThemeColor;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
</summary>
<category term="Mono" scheme="https://shalyf.github.io/categories/Mono/"/>
<category term="macOS" scheme="https://shalyf.github.io/tags/macOS/"/>
<category term="C#" scheme="https://shalyf.github.io/tags/C/"/>
</entry>
<entry>
<title>Mono中各个控件的拖拽实现</title>
<link href="https://shalyf.github.io/2015/nsoutlineview-drag-drop/"/>
<id>https://shalyf.github.io/2015/nsoutlineview-drag-drop/</id>
<published>2015-11-13T06:11:20.000Z</published>
<updated>2017-07-15T15:05:53.000Z</updated>
<content type="html"><![CDATA[<h2 id="NSOutlineView实现拖拽功能"><a href="#NSOutlineView实现拖拽功能" class="headerlink" title="NSOutlineView实现拖拽功能"></a>NSOutlineView实现拖拽功能</h2><h3 id="注册拖拽类型"><a href="#注册拖拽类型" class="headerlink" title="注册拖拽类型"></a>注册拖拽类型</h3><p>在<code>OutlineView</code>的<code>AwakeFromNib</code>中注册</p>
<figure class="highlight cs"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">void</span> <span class="title">AwakeFromNib</span>(<span class="params"></span>)</span></div><div class="line">{</div><div class="line"> <span class="keyword">base</span>.AwakeFromNib();</div><div class="line"> </div><div class="line"> <span class="keyword">this</span>.RegisterForDraggedTypes (<span class="keyword">new</span> <span class="keyword">string</span>[] {</div><div class="line"> NSPasteboard.NSFilenamesType.ToString (),</div><div class="line"> NSPasteboard.NSUrlType.ToString (),</div><div class="line"> NSPasteboard.NSDragPasteboardName.ToString (),</div><div class="line"> NSPasteboard.NSStringType.ToString (),</div><div class="line"> NSPasteboard.NSFilesPromiseType.ToString ()</div><div class="line"> });</div><div class="line"> </div><div class="line"> <span class="keyword">this</span>.SetDraggingSourceOperationMask (NSDragOperation.All, <span class="literal">false</span>);</div><div class="line"> <span class="keyword">this</span>.AllowsMultipleSelection = <span class="literal">true</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<p><code>RegisterForDraggedTypes</code>注册拖动类型,仅有注册的类型才能完成控件内的拖动(有拖动特效),如果是要拖动到控件以外的地方,则可以不用注册。<br><code>SetDraggingSourceOperationMask</code>设置拖动源操作,没有设置的话将不会呼起必须的拖动方法,特别注意第二个参数,置为<code>true</code>表示拖动只能在控件内,置为<code>false</code>表示可以拖动到控件以外。如果需要拖动到桌面等其他文件夹,一定要置为<code>false</code>。</p>
<h3 id="实现OutlineViewwriteItemstoPasteboard方法(在DataSource中)"><a href="#实现OutlineViewwriteItemstoPasteboard方法(在DataSource中)" class="headerlink" title="实现OutlineViewwriteItemstoPasteboard方法(在DataSource中)"></a>实现OutlineViewwriteItemstoPasteboard方法(在DataSource中)</h3><figure class="highlight cs"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">bool</span> <span class="title">OutlineViewwriteItemstoPasteboard</span> (<span class="params">NSOutlineView outlineView, NSArray items, NSPasteboard pboard</span>)</span></div><div class="line">{</div><div class="line"> pboard.DeclareTypes (<span class="keyword">new</span> <span class="keyword">string</span>[] {</div><div class="line"> NSPasteboard.NSFilesPromiseType.ToString () }, <span class="literal">null</span>);</div><div class="line"> <span class="keyword">string</span>[] types = <span class="keyword">new</span> <span class="keyword">string</span>[<span class="number">1</span>] { <span class="string">""</span> };</div><div class="line"> NSArray list = NSArray.FromStrings (types);</div><div class="line"> pboard.SetPropertyListForType (list, NSPasteboard.NSFilesPromiseType.ToString ());</div><div class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<a id="more"></a>
<p>其中<code>pboard.DeclareTypes</code>声明拖拽类型。<br><code>pboard.SetStringForType</code>或<code>pboard.SetDataForType</code>设置拖动的内容。案例使用<code>SetPropertyListForType</code>为粘贴板设置一个列表内容。<br>当拖动类型为<code>NSPasteboard.NSFilenamesType</code>时,<code>list</code>中存储的<code>url</code>必须是针对本机有效的,如果用了无效的<code>url</code>,将无法完成拖动。<br>当拖动类型为<code>NSPasteboard.NSFilesPromiseType</code>时,<code>list</code>可以随便填,但是不能为空,该方法还没有完全理透,不过已经可以通过这个方法来获取目标<code>Url</code>。使用这种拖动类型将会呼起<code>FilesDropped</code>方法,通过该方法就能获得目标<code>Url</code>。</p>
<h3 id="实现DragImage方法(在控件中,需要重写控件,也可以不实现,使用父类方法)"><a href="#实现DragImage方法(在控件中,需要重写控件,也可以不实现,使用父类方法)" class="headerlink" title="实现DragImage方法(在控件中,需要重写控件,也可以不实现,使用父类方法)"></a>实现DragImage方法(在控件中,需要重写控件,也可以不实现,使用父类方法)</h3><figure class="highlight cs"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">void</span> <span class="title">DragImage</span> (<span class="params">NSImage anImage, PointF viewLocation, SizeF initialOffset, NSEvent theEvent, NSPasteboard pboard, NSObject sourceObj, <span class="keyword">bool</span> slideFlag</span>)</span></div><div class="line">{</div><div class="line"> anImage = NSWorkspace.SharedWorkspace.IconForFile (<span class="string">"/Applications/Tongbu.app"</span>);</div><div class="line"> viewLocation = <span class="keyword">this</span>.ConvertPointFromView (theEvent.LocationInWindow, <span class="literal">null</span>);</div><div class="line"> viewLocation.X -= <span class="number">16</span>;</div><div class="line"> viewLocation.Y -= <span class="number">16</span>;</div><div class="line"></div><div class="line"> <span class="keyword">base</span>.DragImage (anImage, viewLocation, initialOffset, theEvent, pboard, sourceObj, slideFlag);</div><div class="line">}</div></pre></td></tr></table></figure>
<p><code>anImage</code>设置拖动时显示的图标,<code>viewLocation</code>设置图标显示的位置。<br>然后调用父类的<code>DragImage</code>方法完成。</p>
<h3 id="实现FilesDropped方法(在DataSource中)"><a href="#实现FilesDropped方法(在DataSource中)" class="headerlink" title="实现FilesDropped方法(在DataSource中)"></a>实现FilesDropped方法(在DataSource中)</h3><p>使用<code>NSPasteboard.NSFilesPromiseType</code>拖动类型时触发<br>如果拖动源不是本机有效的<code>Url</code>,使用<code>NSPasteboard.NSFilenamesType</code>是不允许拖动的,这时候就要用到<code>NSPasteboard.NSFilesPromiseType</code>了。</p>
<figure class="highlight cs"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">string</span>[] <span class="title">FilesDropped</span> (<span class="params">NSOutlineView outlineView, NSUrl dropDestination, NSArray items</span>)</span></div><div class="line">{</div><div class="line"> Console.WriteLine (<span class="string">"dropDestination = "</span> + dropDestination.Path);</div><div class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="keyword">string</span>[] { <span class="string">""</span> } ;</div><div class="line">}</div></pre></td></tr></table></figure>
<p><code>dropDestination</code>为目标<code>Url</code>,获取该<code>Url</code>,就能通过其他手段将需要的文件复制到目的地了。</p>
<h2 id="NSBrowser实现拖拽功能"><a href="#NSBrowser实现拖拽功能" class="headerlink" title="NSBrowser实现拖拽功能"></a>NSBrowser实现拖拽功能</h2><p>知道了<code>NSOutlinView</code>的拖拽实现,<code>NSBrowser</code>也就简单了,只需要找到触发拖动的事件和完成拖动的事件,实现它们就可以了。</p>
<h3 id="注册拖拽类型(同NSOutlineView)"><a href="#注册拖拽类型(同NSOutlineView)" class="headerlink" title="注册拖拽类型(同NSOutlineView)"></a>注册拖拽类型(同NSOutlineView)</h3><h3 id="实现WriteRowsWithIndexesToPasteboard方法(在Delegate中)"><a href="#实现WriteRowsWithIndexesToPasteboard方法(在Delegate中)" class="headerlink" title="实现WriteRowsWithIndexesToPasteboard方法(在Delegate中)"></a>实现WriteRowsWithIndexesToPasteboard方法(在Delegate中)</h3><figure class="highlight cs"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">bool</span> <span class="title">WriteRowsWithIndexesToPasteboard</span> (<span class="params">NSBrowser browser, NSIndexSet rowIndexes, <span class="keyword">int</span> column, NSPasteboard pasteboard</span>)</span></div><div class="line">{</div><div class="line"> <span class="keyword">string</span>[] temp = <span class="keyword">new</span> <span class="keyword">string</span>[<span class="number">1</span>]{<span class="string">""</span>};</div><div class="line"> NSArray fileList = NSArray.FromStrings (temp);</div><div class="line"> pasteboard.DeclareTypes (<span class="keyword">new</span> <span class="keyword">string</span>[] { NSPasteboard.NSFilesPromiseType.ToString() }, <span class="literal">null</span>);</div><div class="line"> pasteboard.SetPropertyListForType (fileList, NSPasteboard.NSFilesPromiseType.ToString());</div><div class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="实现DragImage方法(同NSOutlineView)"><a href="#实现DragImage方法(同NSOutlineView)" class="headerlink" title="实现DragImage方法(同NSOutlineView)"></a>实现DragImage方法(同NSOutlineView)</h3><h3 id="实现PromisedFilesDroppedAtDestination方法(在Delegate中)"><a href="#实现PromisedFilesDroppedAtDestination方法(在Delegate中)" class="headerlink" title="实现PromisedFilesDroppedAtDestination方法(在Delegate中)"></a>实现PromisedFilesDroppedAtDestination方法(在Delegate中)</h3><figure class="highlight cs"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">string</span>[] <span class="title">PromisedFilesDroppedAtDestination</span> (<span class="params">NSBrowser browser, NSUrl dropDestination, NSIndexSet rowIndexes, <span class="keyword">int</span> column</span>)</span></div><div class="line">{</div><div class="line"> Console.WriteLine (<span class="string">"dropDestination = "</span> + dropDestination.Path);</div><div class="line"> Console.WriteLine (rowIndexes.ToString());</div><div class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="keyword">string</span>[]{<span class="string">""</span>} ;</div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="IKImageBrowserView实现拖拽功能"><a href="#IKImageBrowserView实现拖拽功能" class="headerlink" title="IKImageBrowserView实现拖拽功能"></a>IKImageBrowserView实现拖拽功能</h2><p>写入粘贴板的方法与<code>NSTableView</code>类似,使用<code>WriteItemsToPasteboard</code><br>完成拖动的方法因为<code>Mono</code>没有实现<code>PromisedFilesDroppedAtDestination</code>方法,需要映射。</p>
<figure class="highlight cs"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">[<span class="meta">Export (<span class="meta-string">"namesOfPromisedFilesDroppedAtDestination: "</span>)</span>]</div><div class="line"><span class="function">Public <span class="keyword">string</span>[] <span class="title">NamesOfPromisedFliesDroppedAtDestination</span> (<span class="params">NSUrl dropDestination</span>)</span></div><div class="line">{</div><div class="line"> Console.WriteLine (<span class="string">"dropDestination = "</span> + dropDestination.Path);</div><div class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="keyword">string</span>[]{<span class="string">""</span>} ;</div><div class="line">}</div></pre></td></tr></table></figure>
]]></content>
<summary type="html">
<h2 id="NSOutlineView实现拖拽功能"><a href="#NSOutlineView实现拖拽功能" class="headerlink" title="NSOutlineView实现拖拽功能"></a>NSOutlineView实现拖拽功能</h2><h3 id="注册拖拽类型"><a href="#注册拖拽类型" class="headerlink" title="注册拖拽类型"></a>注册拖拽类型</h3><p>在<code>OutlineView</code>的<code>AwakeFromNib</code>中注册</p>
<figure class="highlight cs"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">void</span> <span class="title">AwakeFromNib</span>(<span class="params"></span>)</span></div><div class="line">&#123;</div><div class="line"> <span class="keyword">base</span>.AwakeFromNib();</div><div class="line"> </div><div class="line"> <span class="keyword">this</span>.RegisterForDraggedTypes (<span class="keyword">new</span> <span class="keyword">string</span>[] &#123;</div><div class="line"> NSPasteboard.NSFilenamesType.ToString (),</div><div class="line"> NSPasteboard.NSUrlType.ToString (),</div><div class="line"> NSPasteboard.NSDragPasteboardName.ToString (),</div><div class="line"> NSPasteboard.NSStringType.ToString (),</div><div class="line"> NSPasteboard.NSFilesPromiseType.ToString ()</div><div class="line"> &#125;);</div><div class="line"> </div><div class="line"> <span class="keyword">this</span>.SetDraggingSourceOperationMask (NSDragOperation.All, <span class="literal">false</span>);</div><div class="line"> <span class="keyword">this</span>.AllowsMultipleSelection = <span class="literal">true</span>;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p><code>RegisterForDraggedTypes</code>注册拖动类型,仅有注册的类型才能完成控件内的拖动(有拖动特效),如果是要拖动到控件以外的地方,则可以不用注册。<br><code>SetDraggingSourceOperationMask</code>设置拖动源操作,没有设置的话将不会呼起必须的拖动方法,特别注意第二个参数,置为<code>true</code>表示拖动只能在控件内,置为<code>false</code>表示可以拖动到控件以外。如果需要拖动到桌面等其他文件夹,一定要置为<code>false</code>。</p>
<h3 id="实现OutlineViewwriteItemstoPasteboard方法(在DataSource中)"><a href="#实现OutlineViewwriteItemstoPasteboard方法(在DataSource中)" class="headerlink" title="实现OutlineViewwriteItemstoPasteboard方法(在DataSource中)"></a>实现OutlineViewwriteItemstoPasteboard方法(在DataSource中)</h3><figure class="highlight cs"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">bool</span> <span class="title">OutlineViewwriteItemstoPasteboard</span> (<span class="params">NSOutlineView outlineView, NSArray items, NSPasteboard pboard</span>)</span></div><div class="line">&#123;</div><div class="line"> pboard.DeclareTypes (<span class="keyword">new</span> <span class="keyword">string</span>[] &#123;</div><div class="line"> NSPasteboard.NSFilesPromiseType.ToString () &#125;, <span class="literal">null</span>);</div><div class="line"> <span class="keyword">string</span>[] types = <span class="keyword">new</span> <span class="keyword">string</span>[<span class="number">1</span>] &#123; <span class="string">""</span> &#125;;</div><div class="line"> NSArray list = NSArray.FromStrings (types);</div><div class="line"> pboard.SetPropertyListForType (list, NSPasteboard.NSFilesPromiseType.ToString ());</div><div class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
</summary>
<category term="Mono" scheme="https://shalyf.github.io/categories/Mono/"/>
<category term="macOS" scheme="https://shalyf.github.io/tags/macOS/"/>
<category term="C#" scheme="https://shalyf.github.io/tags/C/"/>
</entry>
</feed>