안녕하세요. IT김군입니다.


오늘은 C# / WPF에서 프로젝트를 관리자 권한으로 실행시키는 방법에 대해 알아보도록 하겠습니다.


우선 Visual Studio를 관리자 권한으로 실행시켜줍니다.


그 후에 관리자 권한으로 실행한 Visual Studio에서 관리자 권한으로 실행시킬 프로젝트를 열어줍니다.




그 후 위와 같이 프로젝트 명을 우클릭하여 속성으로 들어갑니다.


속성에 들어가면 아래와 같은 화면이 나옵니다.


위 처럼 속성에서 보안 탭으로 들어가면


'ClickOnce 보안 설정 사용' 이라는 항목이 나오는데요.


이 항목을 체크했다가 다시 체크를 해재해줍니다.


그 이유는 위 사진 좌측에 보이시는 것과 같이 app.manifest 파일을 생성하기 위함이니, 처음 체크가 되어있지 않을테지만 체크를 했다가 다시 해제해줍니다.


그 다음 app.manifest 파일을 열어보겠습니다.




그럼 몇 줄 내려가지 않고 위 빨간 네모박스의 내용이 보이실텐데요.


위 태그에서 level 값을 아래와 같이 requireAdministrator로 변경해줍니다.




위 항목을 모두 진행하신 후 컴파일하셔서 exe를 실행하시면


관리자 권한으로 실행시킬 수 있습니다.


궁금하신 점이나 잘못된 점이 있다면 댓글주세요.


감사합니다.


WRITTEN BY
IT김군
S/W 개발자 김군의 메모장

,

안녕하세요. IT김군입니다.


오늘은 WPF로 개발 시 전체화면의 View를 만드는 법에 대해 알아보겠습니다.


전체화면으로 실행하고자 하는 페이지의 xaml 파일에 <Window></Window> 태그가 있다면

<Window ~~~~ 여기에 넣어주면 된다.>
   <Grid>
   </Grid>
</Window>

위와 같이 윈도우 여는 태그 안에 아래 설정들을 넣어주면 됩니다.



WindowStyle="None"

기본적으로 보이는 윈도우 창의 템플릿 (최소화, 최대화, 닫기) 등을 없애고 현재 실행 창의 화면만 사각형으로 보여지게 됩니다.



WindowState="Maximized"

모니터의 해상도에 맞추어 실행 창의 크기를 꽉 채워줍니다. (작업표시줄 위까지)



ResizeMode="NoResize"

창의 크기를 조절할 수 없게 만들며, 위 설정들과 함께 사용 시 작업표시줄까지 덮어주며 화면을 꽉 채워줍니다.


위 세 개의 설정을 모두 하고나면 이 프로그램 실행 시 다른 프로그램을 실행할 수 없을 것 같지만


실제로 키보드의 window키나 win+D키를 활용해 빠져나올 수 있기에 해당 프로그램만 실행시키고 싶다면 키보드 부분도 같이 작업해주어야 합니다.


잘못되었거나 궁금하신 사항이 있으시면 댓글주세요.


감사합니다.



WRITTEN BY
IT김군
S/W 개발자 김군의 메모장

,

안녕하세요. IT김군입니다.


Socket.io로 Client에서 통신하는 방법에 대해 적어보도록 하겠습니다.


우선 터미널에서 프로젝트에 패키지를 설치합니다.

$ npm install typings --global
$ typings install dt~socket.io-client --global --save
$ npm install socket.io-client --save



그 다음 Socket.io를 사용하실 페이지에 import 및 생성자에 선언해줍니다.

import { NgZone } from '@angular/core';
import * as io from 'socket.io-client';

export class HomePage{
    constructor(private zone : NgZone){}
}



아래는 socket.io를 연결하는 부분입니다.


socket.io를 연결할 URL에는 http 혹은 https를 무조건 붙여주도록 합니다. (붙이지 않으면 Android에서 인식하지 못합니다.)


아래 console.log 부분의 "this._any_socket.id"는 socket.io가 연결되지 않을 시 undefined로 값이 나오며, socket.io가 연결되었다면 그 id값이 나오게 됩니다.

private _str_socketURL : string = "http://www.yourURL.co.kr:0000";
private _any_socket : any;
private _strarr_chats : string[];

socketConnect(){
   this._any_socket = io(this._str_socketURL);
   this._strarr_chats = [];
   this._any_socket.on('connect', () => {
      console.log("@@ Socket Connect Check : "+this._any_socket.id);
   });
}




이제 socket.io로 연결을 했으니 서버로 정보를 송신해보겠습니다.


아래와 같이 정보를 보내며 'sendEvent'는 서버측과 정해놓은 이벤트 명입니다.


SendValue는 서버측으로 송신할 정보입니다.


이벤트의 경우 서버측과 협의하여야 하며, 이벤트 명을 맞추어 그에 따른 동작에 대해 작업하여야 합니다.

socketSendMsg(){
   this._any_socket.emit('sendEvent', SendValue);
}




이제 보냈으니 받는 부분도 해봐야겠죠?


받는 부분도 보내는 부분과 비슷한 점은 서버측과 협의된 이벤트가 있어야한다는 점입니다. (receiveEvent로 기재했습니다.)


그리고 아래 나온 _strarr_chats는 아까 connect 부분에서 초기화시켜준 변수입니다.

socketReceiveMsg(){
   this._any_socket.on('receiveEvent', (receiveMsg) => {
      this.zone.run(() => {
         this._strarr_chats.push(receiveMsg);
         console.log(receiveMsg);
      })
   });
}




마지막으로 socket.io 연결을 끊는 동작입니다.

socketDisconnect(){
   this._any_socket.disconnect();
}


Socket.io로 서버와 통신하는 기본적인 부분만 기재해보았습니다.


진짜 기본적인 기능만 기재하였고 추가적인 기능은 API를 참조하시면 될 것 같습니다.


Socket.io API  <---- Client API 링크 남깁니다.


감사합니다.


WRITTEN BY
IT김군
S/W 개발자 김군의 메모장

,

안녕하세요. IT김군입니다.


javascript에서 전화번호를 하이픈 없이 입력받아서 사용 후 하이픈을 넣은 값도 필요할 때가 있는데요.


이때 복잡하게 알고리즘으로 해결하시기 보다는 깔끔한 정규식을 추천드립니다.


var phoneNum = "01011111111";
phoneNum = phoneNum.replace(/(^02.{0}|^01.{1}|[0-9]{3})([0-9]+)([0-9]{4})/,"$1-$2-$3");


그리고 모바일 앱을 개발하시는 분들 중에는 입력받는 방식이 아닌 직접 핸드폰 번호를 가져오는 방식을 사용하시는 분들도 계실텐데요.


이 때 +82로 시작하여 국제번호로 들어오는 경우도 있더군요.


그 때 저는 확실한 처리 방법은 아니지만 아래와 같이 처리했습니다. (국내라는 가정하에 작성했습니다.)

ex) 가져온 번호가 var phoneNum = "+821011111111"; 이라고 가정
if(phoneNum.startWith("+")){
    phoneNum = "0"+phoneNum.substring(3);
}

더 좋은 방법 있으면 댓글주세요!


감사합니다.


WRITTEN BY
IT김군
S/W 개발자 김군의 메모장

,

안녕하세요. IT김군입니다.


오늘은 Ionic3에서 이미지 2개를 하나로 합하여 확대, 축소하는 방법까지 알아보도록 하겠습니다.


이 방법을 찾느라 한 일주일은 삽질한 것 같네요.... 처음엔 이미지가 안뜨고 나중에는 이미지를 띄웠더니 Android에서는 작동이 안되고


또 Android를 맞췄더니 IOS가 안되고.......... 그래서 이것저것 삽질하다가 찾은 방법입니다.


우선 image 작업을 하실 페이지 html 파일을 먼저 보겠습니다.

//page.html

<ion-header>
   <ion-navbar>
      <ion-title>
         타이틀명
      </ion-title>
   </ion-navbar>
</ion-header>

<ion-content padding>
   <div class="ion-canvas" hidden>
      <canvas #canvas id="canvas"></canvas>
   </div>
   <img src={{this.compositeImage}} #myImage (click)="presentImage(myImage)"/>
</ion-content>


html은 위와 같이 작성하였습니다.


canvas같은 경우는 어차피 두 이미지를 병합한 하나의 이미지를 this.compositeImage에서 보여주려고 일부러 hidden 처리 하였습니다.


그 다음 Zoom In / Zoom out 기능은 ioinc-img-viewer를 사용할 계획이니 터미널에서 추가해줍니다.

$ npm install --save ionic-img-viewer


추가했으니 app.module.ts에도 추가해줍니다.

import { IonicImageViewerModule } from 'ionic-img-viewer';

@NgModule({
   imports : [
      IonicImageViewerModule
   ]
})
export class AppModule {}


그 다음 이 이미지를 사용하실 페이지에 typescript 파일을 코딩해봅시다!


예를 들어 page.ts라고 하겠습니다.

import { Component, ElementRef, ViewChild } from '@angular/core';
import { NavController, Platform } from 'ionic-angular';
import { ImageViewerController } from 'ionic-img-viewer';

export class Page {

  @ViewChild('canvas') canvasEl : ElementRef;
  
    private _Canvas : any;
  
    private _Context : any;
    private compositeImage;
  
    private image1 : string;
    private image2 : string;
  
    private image : any = new Image();
    private _image : any = new Image();
    private _imageViewerCtrl : ImageViewerController;

  constructor(public navCtrl: NavController, private platform : Platform, 
     private imgViewerCtrl : ImageViewerController) {
    this._imageViewerCtrl = imgViewerCtrl;
  }

  presentImage(myImage){
    const imageViewer = this._imageViewerCtrl.create(myImage);
    imageViewer.present();
  }

  ionViewDidLoad(){
    this._Canvas = document.createElement('canvas');
    this._Canvas.width = (number)canvas width Size;
    this._Canvas.height = (number)canvas height Size;

    this.platform.ready().then(() => {
      if(this._Canvas.getContext){
        this._Context = this._Canvas.getContext('2d');
        
        this.showImage();
      }
    });
  }

  showImage(){
    this.image1 = 'assets/imgs/sky.png';
    this.image2 = 'assets/imgs/img.png';
    this.image.src = this.image1;
    this.image.onload = () => {
      this._Context.drawImage(this.image, 0, 0, (number)widthSize, (number)heightSize);

      this._image.src = this.image2;
      this._image.onload = () => {
        this._Context.drawImage(this._image, 347.315, 317.288, 50, 50 );
  
        this.compositeImage = this._Canvas.toDataURL("image/png");
      }
    };
  }
}


platform.ready().then()이나 onload()의 경우는 Android와 IOS 각 플랫폼에서 실행 시 모두 호환되는 최적의 시점을 찾다보니 사용하였습니다.


(number) width Size나 (number) Height Size에는 원하시는 크기의 숫자를 넣으시면 됩니다.


this._Context.drawImage()의 파라미터는 (new Image(), x축 좌표, y축 좌표, 이미지 넓이, 이미지 높이); 입니다.


그래서 저는 테스트용으로



위 두 그림을 합쳐보았습니다.


그래서 아래와 같은 결과물을 얻을 수 있었습니다.





위 스크린샷에서 이미지를 누르면 Plugin API를 통해 이미지만 따로 표시되는 modal창이 발생하며 이 modal창에서 확대 축소 기능을 사용할 수 있습니다.


투명화 이미지로 사용하시면 투명화 된 그대로 병합됩니다.


혹시나 궁금하신 점 있으시거나 제가 잘못적은 부분이 있다면 댓글 부탁드립니다.


감사합니다.



WRITTEN BY
IT김군
S/W 개발자 김군의 메모장

,

안녕하세요. IT김군입니다.


매일 그냥 선이 길게 늘어지는 이어폰만 꼽고 다니다가 요즘 출퇴근길을 걸어다니면서 날이 추우니 주머니에 손넣다가 이어폰 선이 너무 걸리적거려서 이번에 블루투스 이어폰을 구매해봤습니다.


우선 제가 구매한 제품은 LG HBS-1100 입니다.


집 옆에 LG 베스트샵을 가보니 20만원이 넘어가더군요.... 여기저기 발품을 팔아 국내 정품을 싸게 잘 구매했습니다.



국내 정품을 구매한 이유는 구매일로부터 1년간 LG 서비스센터에서 무상 A/S가 된다고 하네요.


아무래도 처음 사보는 블루투스 이어폰인만큼 A/S를 위해 국내정품을 구매했습니다!


음질 : 저는 우선 막귀라..... 음질에 대해선 크게 차이를 느끼지 못하는 편에 속하는데도 핸드폰을 처음 구매할 때 들어있던 이어폰

           과는 어느정도 차이가 있더군요.

           하지만 위에 말씀드렸듯 막귀라.... 제가 느낀 차이를 상세하게 설명하지는 못하겠습니다.

           톤플러스 1100 모델은 음질은 최상급이라고 하니, 음질에 신경 많이 쓰시는 분들은 구매하셔도 좋을 듯 싶어요.


배터리 : 배터리는 완충 시 음악감상 10시간, 통화 11시간이라고 적혀있었는데 사용해보니 저는 음악감상 8시간정도 가능했습니다.

             그래도 완충까지의 시간은 매우 빠른 편이며, 저는 보조배터리 2만짜리를 가지고 다니기에... 

             배터리에는 크게 신경쓰이지 않았습니다.



디자인 : 우선 저 같은 경우는 주변에 많은 분들이 블루투스 이어폰을 사용하시는데 줄이 치렁치렁하게 늘어져있는 것들이나, 

               줄이 밖으로 나와있는 모델은 싫더라구요... 톤플러스 1100은 이어폰 선을 당겨서 뺀 후 버튼을 누르면 자동으로 

               감겨들어가는 구조로 되어 있어 정리도 매우 편하고 외부가 매우 심플하니 제 마음에 딱 들었습니다.

               줄이 매우 얇은 편이긴 한데 오래 사용하신 분들도 단선은 거의 없었다고 하니 안심하고 사용해도 될 것 같습니다.


중량 : 넥밴드형을 꺼려하시는 분들은 대부분 목이 불편하다. 무겁다. 거추장스럽다. 이런 이유에서 많이들 꺼려하시던데 중량은 

           60g으로 블루투스 이어폰 넥밴드형을 처음 차보는 저에게는 그리 무겁고 거추장스럽지 않았습니다. 

           그냥 오히려 줄이 있는 이어폰보다 매우 편하다고 느꼈습니다.



블루투스 감도 : 요즘 날씨가 많이 추우니 패딩들 많이 입고 다니실텐데요. 저 같은 경우 집에서 회사까지 걸어서 한 시간정도 

                           걸리는데 한 시간 걸으면서 패딩에 핸드폰을 넣고 오다보면 중간중간 0.5초씩 끊길 때가 있더라구요. 

                           (빈번하지는 않습니다. 한 시간 걸으면서 0.5초 텀으로 3번정도)

                        

통화 : 저는 전화도 많이 하기 문에 마이크 부분도 많이 신경을 썼습니다. 통화를 길게 해보고 상대방에게 물어보면 그냥 제가 이전

           에 쓰던 이어폰과 마이크에서 별차이를 못느낀다고 하니 참고하시면 될 것 같습니다. 

          (제가 전화하면서 제가 들어보는 것보다 상대방이 정확하니까요......)


생활방수 : 저는 생활방수에도 많이 신경을 써서 원래는 HBS-A100 모델을 살까하다가.... 

                  그건 디자인이 너무 아니라는 여자친구 EJ의 말에 따라 1100모델을 구매했는데요. 

                  인터넷을 찾아봐도 생활방수가 된다는 곳도 있고 안된다는 곳도 있어서 매장에 가서 직접 물어보니, 

                  땀이나 이런 부분에 대해 극소량의 방수는 갖춰져 있지만 비를 맞거나 하지는 말라고 하더군요.... 

                  조심해서 사용해야겠습니다.



첫 블루투스 이어폰을 구매해서 며칠 사용해본 지극히 주관적인 후기였습니다.


LG HBS-1100 (톤플러스 1100) 모델 구매를 고민하시는 분들께 도움이 됐으면 좋겠습니다.


궁금하신 점 있으시면 댓글 달아주세요.


감사합니다.



WRITTEN BY
IT김군
S/W 개발자 김군의 메모장

,

안녕하세요. IT김군입니다.


저는 사용자가 백그라운드로 이동했다가 포그라운드로 돌아올 때 어떠한 설정이 바뀌었는지 확인할 수가 없기에


해당 이벤트가 필요했습니다.


해당 이벤트를 사용하실 페이지의 ts파일에 아래와 같은 소스를 사용하시면 될 것 같습니다.

import { Platform } from 'ionic-angular';

private toForeground : any;
constructor(private platform : Platform){
   this.toForeground = this.platform.resume.subscribe(() => {
      console.log("Entered Foreground");
   });
}


잘못된 점이나 궁금한 점 있으시면 댓글부탁드립니다.


감사합니다.


WRITTEN BY
IT김군
S/W 개발자 김군의 메모장

,

안녕하세요. IT김군입니다.


사용자 설정같은 부분에 토글(toggle)버튼을 많이들 사용하실텐데요.


이 토글버튼 활용에 대해서 알아보도록 하겠습니다.


아래는 토글 버튼을 추가하실 html에 넣을 소스입니다.

<ion-list>
   <ion-item>
      <ion-label>토글 버튼</ion-label>
         <ion-toggle value="test" [(ngModel)]="test" color="danger" (ionChange)="toogleTest(test)">
         </ion-toggle>
   </ion-item>
</ion-list>

위에서 보시면 test라는 변수와 toggleTest(test)라는 함수를 포함하였습니다.


아래는 typescript 파일의 소스입니다.

private test : boolean = true;

toggleTest(value){
   if(value){
      console.log("toggle Value : "+value); //toggle True
   }else{
      console.log("toggle Value : "+value); //toggle False
   }
}


최초 test변수가 true로 되어있으면 toggle 버튼도 체크되어 있는 상태입니다.


위 html에서 (ionChange)에 toggleTest(test)를 넣었기에 toggle 버튼을 클릭하여 상태가 바뀔 때 마다 toggleTest()에 변동값 (test = true / false)를 파라미터로 활용하여 실행합니다.


위 예제 소스를 보시고 응용해서 사용하시면 될 것 같습니다.


감사합니다.


WRITTEN BY
IT김군
S/W 개발자 김군의 메모장

,

안녕하세요. IT김군입니다.


Ionic Framework로 Cross Platform을 개발할 시 IOS는 종료의 기능을 지원하지 않으니 Android의 종료기능을 구현하셔야 될텐데요.


저 같은 경우는 뒤로가기 두 번으로 App을 종료하는 기능을 자주 사용합니다.


모든 페이지에 다 적용되도록 app.component.ts에 작업하였습니다.


우선 import 작업과 생성자에 선언 작업을 아래와 같이 해줍니다.

import { App, Platform , ToastController } from 'ionic-angular';

constructor(platform : Platform, private app : App, private toastCtrl : ToastController)


위의 작업이 완료되셨다면 저는 생성자 platform.ready().then(() => {'여기'}); 저 플랫폼레디 내부에 아래 소스를 넣었습니다.

// 뒤로가기 두 번 종료
      platform.registerBackButtonAction(() => {
        const overlay = this.app._appRoot._overlayPortal.getActive();
        const nav = this.app.getActiveNav();
        const closeDelay = 2000;
        const spamDelay = 500;

        if(overlay && overlay.dismiss) {
          overlay.dismiss();
        } else if(nav.canGoBack()){
          nav.pop();
        } else if(Date.now() - this.lastBack > spamDelay && !this.allowClose) {
          this.allowClose = true;
          let toast = this.toastCtrl.create({
            message: "'뒤로가기' 버튼을 연속으로 두 번 누르시면 App이 종료됩니다.",
            duration: closeDelay,
            dismissOnPageChange: true
          });
          toast.onDidDismiss(() => {
            this.allowClose = false;
          });
          toast.present();
        } else if(Date.now() - this.lastBack < closeDelay && this.allowClose) {
          platform.exitApp();
        }

        this.lastBack = Date.now();
      });

넣고 나면 정상작동하는 것을 확인하실 수 있습니다.


궁금하신 점이나 제가 틀린 부분이 있다면 댓글달아주세요.


감사합니다.


WRITTEN BY
IT김군
S/W 개발자 김군의 메모장

,

안녕하세요. IT김군입니다.


맥북 프로를 구매한지 얼마 되지 않았는데 아무래도 작업을 많이 해서인지


터미널에서 cd , ls 등등의 자주 쓰는 명령어에도 속도가 빠르게 반응을 하지 않더군요.


그래서 여기저기 찾아본 결과

$ cd /private/var/log/asl/

에 들어가시면 쌓여있는 로그가 있는데 여기서 아래와 같은 명령어로 asl 로그파일을 삭제해주시면 됩니다.

$ sudo rm -rf /private/var/log/asl/*.asl

위와 같이 삭제하고나니 다시 속도가 처음처럼 빨라졌습니다.


도움이 되실 것 같습니다.


P.S asl = Apple System Log


감사합니다.


WRITTEN BY
IT김군
S/W 개발자 김군의 메모장

,