2011年2月27日日曜日

Cocoa ObjC 透明ウィンドウのリサイズ

昨日GiveUpしたのに、本日実現できた、透明ウィンドウのサイズ変更。そんなものか。あきらめたらそこで試合終了、になるところだった。

さて、昨夜あれこれググった果てにこんなフォーラムに行きあたった。

CocoaDev/BorderlessWindow

この記事の中盤以降のソースが透明ウィンドウのリサイズに関する話になっていて、なんとなくこれが正解になりそうと当たりをつける。

本日実際に試してみたら見事にBingo!該当のソースを引用すると
- (void)mouseDragged:(NSEvent *)theEvent
{
 if (shouldRedoInitials)
 {
  initialLocation = [theEvent locationInWindow];
  initialLocationOnScreen = [self convertBaseToScreen:[theEvent locationInWindow]];
  
  initialFrame = [self frame];
  shouldRedoInitials = NO;
  
  if (initialLocation.x > initialFrame.size.width - 20 && initialLocation.y < 20) {
   shouldDrag = NO;
  }
  else {
   //mouseDownType = PALMOUSEDRAGSHOULDMOVE;
   shouldDrag = YES;
  }
  
  screenFrame = [[NSScreen mainScreen] frame];
  windowFrame = [self frame];
  
  minY = windowFrame.origin.y+(windowFrame.size.height-288);
 }
 
 
 // 1. Is the Event a resize drag (test for bottom right-hand corner)?
 if (shouldDrag == FALSE)
 {
  // i. Remember the current downpoint
  NSPoint currentLocationOnScreen = [self convertBaseToScreen:[self mouseLocationOutsideOfEventStream]];
  currentLocation = [theEvent locationInWindow];
  
  // ii. Adjust the frame size accordingly
  float heightDelta = (currentLocationOnScreen.y - initialLocationOnScreen.y);
  
  if ((initialFrame.size.height - heightDelta) < 289)
  {
   windowFrame.size.height = 288;
   //windowFrame.origin.y = initialLocation.y-(initialLocation.y - windowFrame.origin.y)+heightDelta;
   windowFrame.origin.y = minY;
  } else
  {
   windowFrame.size.height = (initialFrame.size.height - heightDelta);
   windowFrame.origin.y = (initialFrame.origin.y + heightDelta);
  }
  
  windowFrame.size.width = initialFrame.size.width + (currentLocation.x - initialLocation.x);
  if (windowFrame.size.width < 323)
  {
   windowFrame.size.width = 323;
  }
  
  // iii. Set
  [self setFrame:windowFrame display:YES animate:NO];
 }
    else
 {
  //grab the current global mouse location; we could just as easily get the mouse location 
  //in the same way as we do in -mouseDown:
  currentLocation = [self convertBaseToScreen:[self mouseLocationOutsideOfEventStream]];
  newOrigin.x = currentLocation.x - initialLocation.x;
  newOrigin.y = currentLocation.y - initialLocation.y;
  
  // Don't let window get dragged up under the menu bar
  if( (newOrigin.y+windowFrame.size.height) > (screenFrame.origin.y+screenFrame.size.height) )
  {
   newOrigin.y=screenFrame.origin.y + (screenFrame.size.height-windowFrame.size.height);
  }
  
  //go ahead and move the window to the new location
  [self setFrameOrigin:newOrigin];
  
 }
}

- (void)mouseUp:(NSEvent *)theEvent
{
 shouldRedoInitials = YES;
}

これをカスタムクラス化したNSWindowに組み込めばそれでOK。ちなみにヘッダには
    BOOL shouldDrag;
 BOOL shouldRedoInitials;
 NSPoint initialLocation;
 NSPoint initialLocationOnScreen;
 NSRect initialFrame;
 NSPoint currentLocation;
 NSPoint newOrigin;
 NSRect screenFrame;
 NSRect windowFrame;
 float minY; 

以上の変数を加えておく。Windowクラスの初期化時に

shouldRedoInitials = YES;

を書いておかないと、マウスのファーストタッチで変な場所にウィンドウが飛ばされる、ということだけ、自分であれこれ試行錯誤して確かめた。
透明ウィンドウなのでマウスのイベント拾わないはずなんだけど、なぜかなにもしないでもイベントを拾うな。
というわけで何日間かのもやもやが晴れてすっきり。自分で考え出したことではないので一点、曇がある感じもするけど(ぜーたく)

今度は環境設定を実装していこう。

0 件のコメント:

コメントを投稿