GSI

UICanvas 전환효과주기 소스


최근에 공부하면서 심플하게 처리하는 방법 정리한 자료 입니다.


유니티_Canvas전환_코드.pdf


UICanvasSwitch2.zip


Posted by gsi
:

Bullet3D 라이브러리를 계속 파오는 동안 벌써 몇달이 지난듯 하다.

 

계속해서 로봇의 움직임을 구동하기 위해서는 객체마다 조건(ex btHingeConstraint)을 걸어줘야 하며,

조건들을 움직이는건 일단 마무리가 되었다

이후에 계속해서 가지고 있던 고민은 다리 하나하나를 움직여야 하니 제일 끝의 객체를

위치 이동을 해보면 좋을거 같았다.

 

그래서 마우스로 객체를 움직일 수 있는 부분을 파 보았다.

두가지의 제어 방식이 보인다.

btGeneric6DofConstraint 이것과 btPoint2PointConstraint 두가지다

 

일단 btPoint2PointConstraint 이걸로 제어를 해보기로 했다.

아래의 코드는 움직임을 제어 하는 방법이다.

 

객체의 변수는 아래와 같이 선언

btPoint2PointConstraint* pConStraint;

 

이 코드는 매번 포인터 객체를 삭제 해야 한다.

if( pConStraint )
{
 m_dynamicsWorld->removeConstraint( pConStraint );
 delete pConStraint;
 pConStraint = NULL;
}

 

// 해당 btRigidBody 를 연결시켜 준다.

btVector3 p1(0, 0, 0);
pConStraint = new btPoint2PointConstraint( *m_rigs[0]->m_bodies[3], p1 );
m_dynamicsWorld->addConstraint( pConStraint, true );
pConStraint->m_setting.m_tau = 1;

 

// 위와 같이 연결하고 나서 아래와 같이 해당 이동값을 적어주면 객체가 움직이게 된다.
btVector3 newPivotB;
newPivotB.setZero();
newPivotB.setZ( 0.1 );
pConStraint->setPivotA( newPivotB );

 

근데 위와 같이 코드를 구성한 이후는 btRigidBody를 Constraint로 연결을 하고

pConStraint->setPivotA( newPivotB ); 를 하고 나면 계속해서 연결이 유지되고

계속해서 움직임을 할 수 있을거라 생각 했지만,

잘 안되서 포인터 객체를 없애고, 다시 연결후에

pConStraint->setPivotA( newPivotB ); 이걸 통해서 위치를 이동시킬 수 있는걸 알았다.

 

이제 앞으로 해야 할것

 

//
pConStraint = NULL;
pConStraint2 = NULL;

//
{
 btVector3 p1(0, 0, 0);
 pConStraint = new btPoint2PointConstraint( *m_rigs[0]->m_bodies[3], p1 );
 m_dynamicsWorld->addConstraint( pConStraint, true );
 pConStraint->m_setting.m_tau = 1;
}
{
 btVector3 p1(0, 0, 0);
 pConStraint2 = new btPoint2PointConstraint( *m_rigs[0]->m_bodies[6], p1 );
 m_dynamicsWorld->addConstraint( pConStraint2, true );
 pConStraint2->m_setting.m_tau = 1;
}

이 코드를 사용해서 해당 객체를 바닥에 고정 시킨다.

 

고정시켜 놓고 나서 시퀀스를 구성하고 하나하나 이동하면서 위치가 앞으로 이동하는지를 보자.

Posted by gsi
:

이 자료는

4족 로봇을 위한 기초자료로서 Bullet3D의 라이브러리 이해를 위해서 정리한 내용임

 

 

 

위의 내용은 로봇암의 한쪽 부분을 설명하기 위한 자료

오른쪽의 마젠타 색상의 사각형이 고정부 그기서 부터 옆으로 관절1, 관절2 형태로 취해진다.

관절2(파란색)을 키보드로 움직이면 중간의 관절1의 각도가 변해야 하는게 목표이다.

 

조금 움직였을때의 모습

 

관절2번을 아래로 회전하게 되면서 관절1번의 각도가 변한 모습이다.

 

위의 화면은 카메라 뷰에서 본 화면이며

객체마다 Axis가 표기 되어 있는데

빨간색 - X

녹색 - Y

파란색 - Z (화면 뒤쪽)

 

아래는 관련된 코드이다.

 

화면에 보이는 객체는 일단 모델링 데이터가 존재 해야 하기 때문에 그 모델링 데이터는

btCollisionShape* m_shapes[2];//BODYPART_COUNT];

이걸로 관리 된다.

이 포인터 객체에 해당 데이터가 생성이 된다.

m_shapes[0] = new btBoxShape(btVector3(fBodySize, fBodySize, fBodySize));
m_shapes[1] = new btBoxShape(btVector3(fBodySize, fBodySize, fBodySize));

이 객체들은 나중에 화면에 객체를 표현하기 위한 인스턴스 객체들이다.

 

아래 코드는 화면에 보여지는 3개의 객체를 만든 내용이다.

  // 높이 0.5에 기본 위치를 잡는다.
  float fHeight = 1.0;
  btTransform offset; offset.setIdentity();
  offset.setOrigin(positionOffset);  

  // root
  // 중앙의 둥근원형을 만든다.
  btVector3 vRoot = btVector3(btScalar(0.), btScalar(fHeight), btScalar(0.));
  btTransform transform;
  transform.setIdentity();
  transform.setOrigin(vRoot);
  // 무게를 0으로 하면 고정형태의 객체가 만들어 진다.
  m_bodies[0] = localCreateRigidBody(btScalar(0.), offset*transform, m_shapes[0]);

  // 다리1
  transform.setIdentity();
  btVector3 vBoneOrigin = btVector3(1.0, 1.0, 0);
  transform.setOrigin(vBoneOrigin);
  btVector3 vToBone = (vBoneOrigin - vRoot).normalize();
  btVector3 vAxis = vToBone.cross(vUp);
  m_bodies[1] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[1]);

  // 다리 2
  transform.setIdentity();
  vBoneOrigin = btVector3(2.0, 1.0, 0);
  transform.setOrigin(vBoneOrigin);
  vToBone = (vBoneOrigin - vRoot).normalize();
  vAxis = vToBone.cross(vUp);
  m_bodies[2] = localCreateRigidBody(btScalar(1.), offset*transform, m_shapes[1]);

 

위의 내용으로 화면에 보여지는 객체를 만들고 나면 이제 객체들을 연결하기 위한 조인트를 연결해 줘야 한다.

이걸 하지 않으면 무게 1짜리가 바닥으로 바로 떨어지게 된다. 중력이 있기 때문에.

 

아래 코드는 Hing를 추가 하는 모습이다.

나중에 서보 모터를 연동하기 위함이기 때문에 Hing라는 걸로 연결하도록 한다.

 

  btHingeConstraint* hingeC;
  //btConeTwistConstraint* coneC;

  btTransform localA, localB, localC, localD;

  float fAngle = 0;
  float fSin = sin(fAngle);
  float fCos = cos(fAngle);

  // hip joints
  localA.setIdentity();
  localB.setIdentity();
  localA.getBasis().setEulerZYX(0,0,0); 
  localA.setOrigin(btVector3(0.5, -0.5, 0));
  localB.getBasis().setEulerZYX(0,0,0); 
  localB.setOrigin(btVector3(-0.5, -0.5, 0));

  hingeC = new btHingeConstraint(*m_bodies[0], *m_bodies[1], localA, localB);
  hingeC->setLimit(DEG2RAD(0), DEG2RAD(90));
  m_joints[0] = hingeC;
  m_ownerWorld->addConstraint(m_joints[0], true);

  // hip joints
  localA.setIdentity();
  localB.setIdentity();
  localA.getBasis().setEulerZYX(0,0,0); 
  localA.setOrigin(btVector3(0.5, -0.5, 0));
  localB.getBasis().setEulerZYX(0,0,0); 
  localB.setOrigin(btVector3(-0.5, -0.5, 0));

  hingeC = new btHingeConstraint(*m_bodies[1], *m_bodies[2], localA, localB);
  hingeC->setLimit(0.0f, 0.0f);
  m_joints[1] = hingeC;
  m_ownerWorld->addConstraint(m_joints[1], true);

 

위의 코드와 같이 구성하게 되면 Hing로 3개의 객체가 연결이 되게 된다.

 

위의 모델에서 관절2를 움직이기 위한 코드는 아래와 같이 작성하면 된다.

 

 // 해당 모델을 선택된 상태로 가져와야 한다.

 // 이걸 하지 않으면 객체는 업데이트 자체가 되지 않는다. (왜 인지는 모르겠다.)

 m_rigs[0]->m_bodies[2]->setActivationState(DISABLE_DEACTIVATION);

 // Hing 객체를 찾는다. (미리 알고 있기 때문에 배열값을 바로 가져온다.)

 btHingeConstraint* hingeC = static_cast<btHingeConstraint*>(m_rigs[0]->GetJoints()[1]);
 if( hingeC )
 {
  btScalar hingeAngle = hingeC->getHingeAngle(); // 참고용
  btScalar hingeLow = hingeC->getLowerLimit(); // 참고용
  btScalar hingeHigh = hingeC->getUpperLimit(); // 참고용

  // 이걸 보면 알 수 있듯이 해당 객체의 Hing의 각도를 그냥 하나로 고정시켜서 키보드 값으로 이동 가능하게 처리 하였다.

  hingeC->setLimit(DEG2RAD(n_TestAngle), DEG2RAD(n_TestAngle));

  >> hingeC->setLimit(DEG2RAD(n_TestAngle), DEG2RAD(n_TestAngle), 0, 1, 0); 이걸로 고치면 움직임이 조금더 빠르다. 소프트한게 없어지고..

  // 모델 생성시 아래 코드도 그냥 0으로 바꾸면 움직임이 조금더 빨라진다.

  for (i = 0; i < 3; ++i)
  {
   m_bodies[i]->setDamping(0, 0); // 이 값이 크지면 중력의 영향을 천천히 받아서 모델이 천천히 떨어진다.
   m_bodies[i]->setDeactivationTime(0);
   m_bodies[i]->setSleepingThresholds(0, 0);
  }

 

  // 아래 코드는 굳이 하지 않아도 동작은 한다.
  hingeC->enableAngularMotor(false, 0, 0);
 }

 

아래는 관련 코드입니다.

 

BulletTestApp_분석용_Constraint.zip

 

 

 

 

 

 

 

Posted by gsi
:

mackeybind.exe 이 파일을 실행하고 오른쪽 command, option 키를

누를때 한글 및 한자 키가 먹도록 할 수 있습니다.

 

원래 부트 캠프로 설정이 되었는데

어느 순간부터 되지 않아서

새로 셋팅했습니다.

Posted by gsi
:

[기능]
- 카메라를 통한 사진 선택
- 롤 이미지에서 사진 선택
- 도큐먼트에 이미지 저장
- 새로 실행할때 도큐먼트 이미지 로드 기능

-h 코드

//

//  DocumentTestViewController.h

//  DocumentTest

//

//  Created by 병욱 on 11. 5. 1..

//  Copyright 2011 GsiSystem. All rights reserved.

//


#import <UIKit/UIKit.h>


#define kFilename @"data.plist"

#define kImageFilename @"Test.png"


@interface DocumentTestViewController : UIViewController<UIImagePickerControllerDelegate, UINavigationControllerDelegate> {

IBOutlet UIImageView *imageView;

IBOutlet UIButton *takePictureButton;

IBOutlet UIButton *selectFromCameraRollButton;

IBOutlet UITextField *field1;

IBOutlet UITextField *field2;

IBOutlet UITextField *field3;

IBOutlet UITextField *field4;

}


@property (nonatomic, retain) UIImageView *imageView;

@property (nonatomic, retain) UIButton *takePictureButton;

@property (nonatomic, retain) UIButton *selectFromCameraRollButton;


@property (nonatomic, retain) UITextField *field1;

@property (nonatomic, retain) UITextField *field2;

@property (nonatomic, retain) UITextField *field3;

@property (nonatomic, retain) UITextField *field4;


- (NSString *)dataFilePath;

- (NSString *)dataImageFilePath;

- (void) applicationWillTerminate:(NSNotification *)notification;

- (IBAction)getCameraPicture:(id)sender;

- (IBAction)selectExistingPicture;


@end


- m 코드

//

//  DocumentTestViewController.m

//  DocumentTest

//

//  Created by 병욱 on 11. 5. 1..

//  Copyright 2011 GsiSystem. All rights reserved.

//


#import "DocumentTestViewController.h"


@implementation DocumentTestViewController


@synthesize field1, field2, field3, field4;

@synthesize imageView;

@synthesize takePictureButton;

@synthesize selectFromCameraRollButton;


/*

// The designated initializer. Override to perform setup that is required before the view is loaded.

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

    if (self) {

        // Custom initialization

    }

    return self;

}

*/


/*

// Implement loadView to create a view hierarchy programmatically, without using a nib.

- (void)loadView {

}

*/


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.

- (void)viewDidLoad {

//    [super viewDidLoad];

//

NSString *filePath = [self dataFilePath];

if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {

NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];

field1.text = [array objectAtIndex:0];

field2.text = [array objectAtIndex:1];

field3.text = [array objectAtIndex:2];

field4.text = [array objectAtIndex:3];

[array release];

}

//

NSString *imageFilePath = [self dataImageFilePath];

if ([[NSFileManager defaultManager] fileExistsAtPath:imageFilePath]) {

UIImage *image = [UIImage imageWithContentsOfFile:imageFilePath];

imageView.image = image;

}

//

UIApplication *app = [UIApplication sharedApplication];

[[NSNotificationCenter defaultCenter] addObserver:self 

selector:@selector(applicationWillTerminate:) 

name:UIApplicationWillTerminateNotification 

  object:app];

[super viewDidLoad];

//

if (![UIImagePickerController isSourceTypeAvailable:

  UIImagePickerControllerSourceTypeCamera]) {

takePictureButton.hidden = YES;

selectFromCameraRollButton.hidden = YES;

}

}


- (NSString *)dataFilePath

{

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *documentsDirectory = [paths objectAtIndex:0];

return [documentsDirectory stringByAppendingPathComponent:kFilename];

}


- (NSString *)dataImageFilePath

{

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *documentsDirectory = [paths objectAtIndex:0];

return [documentsDirectory stringByAppendingPathComponent:kImageFilename];

}


- (void) applicationWillTerminate:(NSNotification *)notification

{

NSMutableArray *array = [[NSMutableArray alloc] init];

[array addObject:field1.text];

[array addObject:field2.text];

[array addObject:field3.text];

[array addObject:field4.text];

[array writeToFile:[self dataFilePath] atomically:YES];

[array release];

}


/*

// Override to allow orientations other than the default portrait orientation.

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

    // Return YES for supported orientations

    return (interfaceOrientation == UIInterfaceOrientationPortrait);

}

*/


- (void)didReceiveMemoryWarning {

// Releases the view if it doesn't have a superview.

    [super didReceiveMemoryWarning];

// Release any cached data, images, etc that aren't in use.

}


- (void)viewDidUnload {

// Release any retained subviews of the main view.

// e.g. self.myOutlet = nil;

}



- (void)dealloc {

    [super dealloc];

[field1 release];

[field2 release];

[field3 release];

[field4 release];

[imageView release];

[takePictureButton release];

[selectFromCameraRollButton release];

}


- (IBAction)getCameraPicture:(id)sender

{

UIImagePickerController *picker = 

[[UIImagePickerController alloc] init];

picker.delegate = self;

picker.allowsImageEditing = YES;

picker.sourceType = (sender == takePictureButton) ?

UIImagePickerControllerSourceTypeCamera

UIImagePickerControllerSourceTypeSavedPhotosAlbum;

[self presentModalViewController:picker animated:YES];

[picker release];

}


- (IBAction)selectExistingPicture

{

if ([UIImagePickerController isSourceTypeAvailable:

UIImagePickerControllerSourceTypePhotoLibrary]) {

UIImagePickerController *picker = 

[[UIImagePickerController alloc] init];

picker.delegate = self;

picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

picker.allowsImageEditing = YES;

[self presentModalViewController:picker animated:YES];

[picker release];

}

else {

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error accessing photo library"

message:@"Device does not support a photo library"

  delegate:nil

  cancelButtonTitle:@"Drat!"

  otherButtonTitles:nil];

[alert show];

[alert release];

}

}


- (void)imagePickerController:(UIImagePickerController *)picker

didFinishPickingImage:(UIImage *)image

  editingInfo:(NSDictionary *)editingInfo {

imageView.image = image;

printf("Image:%f, %f", image.size.width, image.size.height);

[UIImagePNGRepresentation(image) writeToFile:[self dataImageFilePath]

  atomically:YES];

[picker dismissModalViewControllerAnimated:YES];

}


- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker

{

[picker dismissModalViewControllerAnimated:YES];

}


@end


- 인터페이스 빌더 내용
캡춰 맥에서 어케 하는지 몰겠군요. ^^
 
Posted by gsi
:

POST로 데이터를 보낼때 NSDictionary를 사용하면 되는데 스타일은
아래의 코드와 같이 실제 값이 앞에 가고 뒤에 이름이 들어간다.

[뷰에 클릭후 http를 생성 및 초기 코드]

// url 문자열을 이용하여 HTTP 웹사이트에 접속

- (void)requestUrl {

    // 접속할 주소 설정

    NSString *url = @"http://사용자의 웹 페이지 주소";

    

    // HTTP Request 인스턴스 생성

    HTTPRequest *httpRequest = [[HTTPRequest alloc] init];

    

    // POST 전송할 데이터 설정

    NSDictionary *bodyObject = [NSDictionary dictionaryWithObjectsAndKeys:

@"38.0", @"latitude"

@"127.0", @"longitude",

nil];

//NSString *bodyObject = @"type=getUser&seq=1&latitude=38.0&longitude=127.0&time=13600&unit='k'&distance=9999";

    

    // 통신 완료 호출할 델리게이트 셀렉터 설정

    [httpRequest setDelegate:self selector:@selector(didReceiveFinished:)];

    

    // 페이지 호출

    [httpRequest requestUrl:url bodyObject:bodyObject];

//

[spinner startAnimating];

}


아래 코드들은 클래스 생성후에 내용을 추가 해야 합니다.
[HTTPRequest.h]

#import <Foundation/Foundation.h>



@interface HTTPRequest : NSObject

{

    NSMutableData *receivedData;

    NSURLResponse *response;

    NSString *result;

    id target;

    SEL selector;

}


- (BOOL)requestUrl:(NSString *)url bodyObject:(NSDictionary *)bodyObject;

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)aResponse;

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;

- (void)connectionDidFinishLoading:(NSURLConnection *)connection;

- (void)setDelegate:(id)aTarget selector:(SEL)aSelector;


@property (nonatomic, retain) NSMutableData *receivedData;

@property (nonatomic, retain) NSURLResponse *response;

@property (nonatomic, assign) NSString *result;

@property (nonatomic, assign) id target;

@property (nonatomic, assign) SEL selector;


@end



[HTTPRequest.m]

#import "HTTPRequest.h"


@implementation HTTPRequest


@synthesize receivedData;

@synthesize response;

@synthesize result;

@synthesize target;

@synthesize selector;


- (BOOL)requestUrl:(NSString *)url bodyObject:(NSDictionary *)bodyObject

{

    // URL Request 객체 생성

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]

                                                           cachePolicy:NSURLRequestUseProtocolCachePolicy

                                                       timeoutInterval:5.0f];

    

    // 통신방식 정의 (POST, GET)

    [request setHTTPMethod:@"POST"];

    

    // bodyObject 객체가 존재할 경우 QueryString형태로 변환

    if(bodyObject)

    {

        // 임시 변수 선언

        NSMutableArray *parts = [NSMutableArray array];

        NSString *part;

        id key;

        id value;

        

        // 값을 하나하나 변환

        for(key in bodyObject)

        {

            value = [bodyObject objectForKey:key];

            part = [NSString stringWithFormat:@"%@=%@", [key stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],

[value stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

            [parts addObject:part];

        }

        

        // 값들을 & 연결하여 Body 사용

        [request setHTTPBody:[[parts componentsJoinedByString:@"&"] dataUsingEncoding:NSUTF8StringEncoding]];

    }

    

    // Request 사용하여 실제 연결을 시도하는 NSURLConnection 인스턴스 생성

    NSURLConnection *connection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];

    

    // 정상적으로 연결이 되었다면

    if(connection)

    {

        // 데이터를 전송받을 멤버 변수 초기화

        receivedData = [[NSMutableData alloc] init];

        return YES;

    }

    

    return NO;

}


- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)aResponse

{

    // 데이터를 전송받기 전에 호출되는 메서드, 우선 Response 헤더만을 먼저 받아 온다.

    //[receivedData setLength:0];

    self.response = aResponse;

}


- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

{

    // 데이터를 전송받는 도중에 호출되는 메서드, 여러번에 나누어 호출될 있으므로 appendData 사용한다.

    [receivedData appendData:data];

}


- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

{

    // 에러가 발생되었을 경우 호출되는 메서드

    NSLog(@"Error: %@", [error localizedDescription]);

}


- (void)connectionDidFinishLoading:(NSURLConnection *)connection

{

    // 데이터 전송이 끝났을 호출되는 메서드, 전송받은 데이터를 NSString형태로 변환한다.

    result = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];

    

    // 델리게이트가 설정되어있다면 실행한다.

    if(target)

    {

        [target performSelector:selector withObject:result];

    }

}


- (void)setDelegate:(id)aTarget selector:(SEL)aSelector

{

    // 데이터 수신이 완료된 이후에 호출될 메서드의 정보를 담고 있는 셀렉터 설정

    self.target = aTarget;

    self.selector = aSelector;

}


- (void)dealloc

{

    [receivedData release];

    [response release];

    [result release];

    [super dealloc];

}


@end


 
Posted by gsi
:


MFC의 Dialog 베이스를 사용해서 폼을 하나 제작합니다.
그리고 picture Box 를 하나 제작한 후에 CxImage를 사용해서 png 파일을 하나 로드 한후에
picture Box에 SetBitmap 를 하고 나서 이걸 다른 형태로 테스트를 진행해 봤습니다.

기본 코드는 아래와 같아요.

// CxImage 객체 생성
m_pImage = new CxImage("D:\\Test.png", CXIMAGE_FORMAT_PNG);

// PictureBox 컨트롤에 CxImage 이미지 연동
m_pic.SetBitmap( m_pImage->MakeBitmap() );

이렇게 하고 나서 실행 하고, 종료 하게 되면 크게 문제는 안되는듯 하다.

이걸 다른 형태로 테스트를 해봤다.
타이머를 통해서 CxImage 객체 두개의 Bitmap를 m_pic(PictureBox) 컨트롤에 SetBitmap를 반복해서 처리해봤다.

void CPngToBitmapDlg::OnTimer(UINT nIDEvent)
{
 static bool bFirst = false;
 static HBITMAP hBitmap = NULL;

 if( bFirst == false )
 { 
  hBitmap = m_pic.SetBitmap( m_pImage2->MakeBitmap() );
 }
 else
 {
  hBitmap = m_pic.SetBitmap( m_pImage->MakeBitmap() );
 }

 ::DeleteObject( hBitmap );

 //
 bFirst = !bFirst;

 m_loopCount++;
 UpdateData(false);
 

 CDialog::OnTimer(nIDEvent);
}

위의 붉은색 코드를 하지 않고 계속해서 SetBitmap을 하게 되면
페이지파일(PF)가 계속 증가 하는 것을 볼 수 있다.

앞으로 코드 구현을 할때 하나 하나 단위테스트를 통해서 반복적인 메모리 및 GDI 사용량 등을
체크 하고 좀 안정성 있는 프로그램을 하도록 해야 할거 같다.

Posted by gsi
:


참고자료 : http://www.codeproject.com/KB/cs/control_e_appliances.aspx

1. hwinterface.ocx 를 regsvr32 를 통해서 등록한다.
2. Visual Studio 의 도구 상자에서 ocx 를 등록한다.
   - Hwinterface Control의 activex 컨트롤이 생긴다.
3. 해당 폼으로 가져와서 인스턴스를 생성한다.
4. 나머지 코드는 참고 자료의 링크에 존재 하는 파일을 참고 하기 바람

Posted by gsi
:

MD5 샘플 코드

C# 2009. 12. 23. 13:44 |


--선언--
using System.Security.Cryptography;

--코드--
        #region MD5 메소드
        static string getMd5Hash(string input)
        {
            // Create a new instance of the MD5CryptoServiceProvider object.
            MD5 md5Hasher = MD5.Create();

            // Convert the input string to a byte array and compute the hash.
            byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));

            // Create a new Stringbuilder to collect the bytes
            // and create a string.
            StringBuilder sBuilder = new StringBuilder();

            // Loop through each byte of the hashed data
            // and format each one as a hexadecimal string.
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }

            // Return the hexadecimal string.
            return sBuilder.ToString();
        }

        // Verify a hash against a string.
        static bool verifyMd5Hash(string input, string hash)
        {
            // Hash the input.
            string hashOfInput = getMd5Hash(input);

            // Create a StringComparer an comare the hashes.
            StringComparer comparer = StringComparer.OrdinalIgnoreCase;

            if (0 == comparer.Compare(hashOfInput, hash))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        #endregion

        #region MD5 테스트 블록
        private void button1_Click(object sender, EventArgs e)
        {
            // 암호화 문자열을 가져온다.
            string convmd5 = getMd5Hash(textBox1.Text);

            // 암호화된 내용을 출력한다.
            textBox2.Text = convmd5;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            // 해당 문자열을 가져와서 암호화된 내용과 비교 한다.
            if (verifyMd5Hash(textBox3.Text, textBox2.Text) == true)
            {
                MessageBox.Show("맞습니다.");
            }
            else
            {
                MessageBox.Show("틀립니다.");
            }
        }
        #endregion

Posted by gsi
:


WebBrowser를 사용해야 되는 부분이 생겨서
많이 자료를 보고 해봤지만 TopMost라는 특성 때문에 Winform, WPF 모두
원하는 효과를 낼수가 없더라구요.

그래서 여러가지 보고 테스트도 해봤지만.
어떤건 속도가 너무 느리더라구요.

아래 코드는 완전 해결한건 아니지만,
이것도 조금은 접근이 된거 같아요.

목표점은
- 스레드를 통한 백그라운드 처리를 통해서 다른 UI의 동작을 원할하게 처리
-  모자이크 처리로 화면에 출력함으로 해서 조금은 이펙트를 중점으로 한다.

아래의 코드는 일부 접근된 코드를 우선 올려 봅니다.

-- Code --
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Media;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        WebBrowser web = new WebBrowser();

        public Form1()
        {
            InitializeComponent();

            web.Width = 1000;
            web.Height = 1000;
            web.ScrollBarsEnabled = false;
            web.ScriptErrorsSuppressed = true;
            web.Navigate("http://dev.iamgsi.com/googlemap");

            timer1.Start();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //while (web.ReadyState != WebBrowserReadyState.Complete)
            //    System.Windows.Forms.Application.DoEvents();
            //System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));

            int width = web.Document.Body.ScrollRectangle.Width;
            int height = web.Document.Body.ScrollRectangle.Height;
            web.Width = width;
            web.Height = height;

            System.Drawing.Bitmap bmp = new Bitmap(width, height);
            web.DrawToBitmap(bmp, new System.Drawing.Rectangle(0, 0, width, height));

            this.pictureBox1.Width = width;
            this.pictureBox1.Height = height;
            if (this.pictureBox1.Image != null)
            {
                this.pictureBox1.Image.Dispose();
            }
            this.pictureBox1.Image = null;
            this.pictureBox1.Image = bmp;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            web.Document.InvokeScript("MoveAddress", new object[] { "서울" });
        }

        private void button3_Click(object sender, EventArgs e)
        {
            web.Document.InvokeScript("MoveAddress", new object[] { "거창" });
        }

        private void button4_Click(object sender, EventArgs e)
        {
            web.Document.InvokeScript("MoveAddress", new object[] { "광주" });
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (web.ReadyState != WebBrowserReadyState.Complete)
                return;

            int width = web.Document.Body.ScrollRectangle.Width;
            int height = web.Document.Body.ScrollRectangle.Height;
            web.Width = width;
            web.Height = height;

            System.Drawing.Bitmap bmp = new Bitmap(width, height);
            web.DrawToBitmap(bmp, new System.Drawing.Rectangle(0, 0, width, height));

            this.pictureBox1.Width = width;
            this.pictureBox1.Height = height;
            if (this.pictureBox1.Image != null)
            {
                this.pictureBox1.Image.Dispose();
            }
            this.pictureBox1.Image = null;
            this.pictureBox1.Image = bmp;
        }
    }
}

Posted by gsi
:

C# USB 인식 심플한 코드

C# 2009. 12. 15. 18:25 |


    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            bool bFind = false;

            // USB 상태 체크
            DriveInfo [] diArray = DriveInfo.GetDrives();
            foreach (DriveInfo di in diArray)
            {
                if (di.IsReady == true && di.DriveType == DriveType.Removable)
                {
                    bFind = true;
                    break;
                }
            }

            label1.Text = (bFind == true) ? "존재합니다." : "없습니다.";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            timer1.Start();
        }
    }

Posted by gsi
:


    public partial class ucPanel : UserControl
    {
        public ucPanel()
        {
            InitializeComponent();

            //
            backgroundWorker1.RunWorkerAsync();
        }

        static public Font ChangeFontSize2(Font font, float fontSize, GraphicsUnit unit)
        {
            if (font != null)
            {
                float currentSize = font.Size;
                if (currentSize != fontSize)
                {
                    font = new Font(font.Name, fontSize,
                        font.Style, unit,
                        font.GdiCharSet, font.GdiVerticalFont);
                }
            }
            return font;
        }

        public delegate void OnAddNode(string title, int x, int y);
        public void AddNode(string title, int x, int y)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new OnAddNode(this.AddNode), new object[] { title, x, y });
                return;
            }

            // 객체 추가
            Label lbl2 = new Label();
            lbl2.AutoSize = true;
            lbl2.Text = title;
            lbl2.Font = ChangeFontSize2(lbl2.Font, lbl2.Font.Size * 2, GraphicsUnit.Pixel);
            lbl2.Left = x;
            lbl2.Top = y;
            this.Controls.Add(lbl2);

            ucNode ucn = new ucNode();
            ucn.Left = x;
            ucn.Top = y;
            this.Controls.Add(ucn);
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            int breakCount = 0;
            Random rand = new Random();

            while (true)
            {
                //
                this.Invoke(new OnAddNode(this.AddNode), new object[] { "test", rand.Next(10, 738), rand.Next(10, 460) });

                System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));

                //
                breakCount++;
                if (breakCount > 100)
                {
                    break;
                }
            }
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

        }
    }

Posted by gsi
:

WebBrowser 처리방식.. 참..

WPF 2009. 12. 7. 06:09 |


2일 정도 자료를 찾아 보고 했지만.
WebBrowser 는 왜 WPF의 렌더링 방식과 차이가 있는지 모르겠다.
왜냐하면 WebBrowser 위에 다른걸 그리고 싶었지만.
되지 않더라..

그래서 자료를 보다 보니. BitmapSource 라는걸 사용해서 WPF의 렌더링 방식에
맞출수 있다는걸 알았다.
뭐 용어는 잘 모르겠고 암튼 이런 방식인게다. 쩝..
산넘어 산인거지..

우선 이걸 해결 하고 나니 몇가지 더 테스트 할게 남아 있다.
실제 WebBrowser는 숨겨 놓고 Image 같은데 실시간으로 뿌리면서 드로잉 해야 한다는 것과
숨겨 놓은 웹의 Mouse, Keyboard 등의 접근을 또 어떻게 처리 해야 하느냔데..

암튼 더 고민해봐야 할듯 하다.
아래 자료는 최종 코드...

-- Source --
<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="600" Width="1000" xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration">

    <Grid>
        <WebBrowser x:Name="webbrowser" Source="http://www.naver.com" Margin="0,0,437,199" />
       
        <Button Height="23" HorizontalAlignment="Right" Margin="0,104,307,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click">Button</Button>
        <Image HorizontalAlignment="Right" Margin="0,178,18,21" Name="image1" Stretch="Fill" Width="399" />
    </Grid>

</Window>

..
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;


namespace WpfApplication1
{
    /// <summary> 
    /// Interaction logic for Window1.xaml 
    /// </summary> 
    public partial class Window1 : Window
    {
        BitmapSource bitmapsource = null;

        [DllImport("user32.dll", SetLastError = true)]
        static extern bool PrintWindow(IntPtr hwnd, IntPtr hDC, uint nFlags);

        [DllImport("gdi32.dll")]
        public static extern bool DeleteObject(IntPtr hObject);
       
        public Window1()
        {
            InitializeComponent();
        }

        BitmapSource GetScreenInt()
        {
            Bitmap bm = new Bitmap((int)300, (int)300);
            IntPtr hBitmap = bm.GetHbitmap();
            Graphics g = Graphics.FromImage(bm);
            PrintWindow(this.webbrowser.Handle, g.GetHdc(), 0);

            g.ReleaseHdc();

            g.Flush();

            BitmapSource src = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bm.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty,
                System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
            src.Freeze();

            bm.Dispose();
            bm = null;
            DeleteObject(hBitmap);

            return src;

        }
       
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            this.image1.Source = null;
            this.image1.Source = GetScreenInt();
        }
    } 
}

Posted by gsi
:

SELECT REPLACE(CONVERT(varchar(max),textvalue), Substring(textvalue,Len(textvalue)-1,2),'**')
from TBL_TEST_DB

textvalue의 값이 12345 라고 하면 123** 로 치환한다.
Posted by gsi
:


구글이라던지 이곳저곳 찾아 보면 상당히 많은 예제가 나오는거 같다.
GsiClip을 제작중에 DB에 이미지를 데이터로 추가 해야 하는 부분에
단위 테스트에 사용한 소스 코드임. (테스트 수행)

        private void button1_Click(object sender, EventArgs e)
        {
            // 이미지를 DB로 저장한다.
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                ImageSave(openFileDialog1.FileName);

                MessageBox.Show("저장완료");
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            // 이미지를 DB에서 로드한다.
            dsImageTableAdapters.Test1TableAdapter adapter =
                new ImageSaveDB.dsImageTableAdapters.Test1TableAdapter();
            dsImage.Test1DataTable table =
                new dsImage.Test1DataTable();

            adapter.Fill(table);

            if (table.Count > 0)
            {
                pictureBox1.Image = byteArrayToImage(table[0].Content2);
            }
        }

        public Image byteArrayToImage(byte[] byteArrayIn)
        {
            MemoryStream ms = new MemoryStream(byteArrayIn);
            Image returnImage = Image.FromStream(ms);
            return returnImage;
        }

        byte[] ReadFile(string sPath)
        {
            byte[] data = null;

            //
            FileInfo fInfo = new FileInfo(sPath);
            long numBytes = fInfo.Length;
            //
            FileStream fStream = new FileStream(sPath, FileMode.Open, FileAccess.Read);
            //
            BinaryReader br = new BinaryReader(fStream);
            //
            data = br.ReadBytes((int)numBytes);

            return data;
        }

        private void ImageSave(string filename)
        {
            byte[] imageData = ReadFile(filename);

            //
            dsImageTableAdapters.Test1TableAdapter adapter =
                new ImageSaveDB.dsImageTableAdapters.Test1TableAdapter();

            adapter.Insert(imageData);
        }

Posted by gsi
: